⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winsockutil.pas

📁 VC++实现的时间同步程序
💻 PAS
字号:
unit WinsockUtil;

interface

uses Classes, Dialogs, SysUtils, Winsock;

var
  WSData: WSAData;

function StrToAddr(const s: string): longword;
procedure QuickSendUDP(const h: string; const port: integer;
  var Data; const DataLen: integer);
procedure GetLocalAddresses(const s: TStrings);
function HaveLocalAddress: boolean;

type
  TQuickUDPServerThread = class(TThread)
  private
    FListenPort: Word;
    listener: sockaddr_in;
    arg: integer;
    ExceptMsg: string;
    procedure ShowError;
  protected
    Sock: TSocket;
    Remote: sockaddr_in;
    Req: array[1..1024] of byte;
    Req_Len: integer;
    procedure Execute; override;
    procedure DoRequest; virtual; abstract;
  public
    constructor Create(const Suspended: boolean; const ListenPort: Word);
  end;

implementation

type
  PLongWord = ^LongWord;

function StrToAddr(const s: string): longword;

var
  pHE: PHostEnt;

begin
  result := inet_addr(pchar(s));
  if result = longword(INADDR_NONE) then
    begin
      pHE := GetHostByName(pchar(s));
      if pHE = nil then
        result := longword(INADDR_NONE)
      else
        result := LongWord(PLongWord(pHE^.h_addr_list^)^);
    end;
end;

function HaveLocalAddress: boolean;

var
  sl: TStringList;

begin
  sl := TStringList.Create;
  try
    GetLocalAddresses(sl);
    result := (sl.Count <> 0) and ((sl.Count > 1) or (sl[0] <> '127.0.0.1'));
  finally
    sl.Free;
  end;
end;

procedure GetLocalAddresses(const s: TStrings);

type
  TaPInAddr = array[0..250] of PInAddr;
  PaPInAddr = ^TaPInAddr;

var
  i: integer;
  HostAddr: PHostEnt;
  PAdrPtr: PaPInAddr;
  HostName: string;

begin
  s.Clear;
  setlength(HostName,255);
  GetHostName(pchar(HostName),255);
  setlength(HostName,strlen(pchar(HostName)));
  HostAddr := GetHostByName(PChar(HostName));
  if HostAddr = nil then
    exit;
  PAdrPtr := PAPInAddr(HostAddr^.h_addr_list);
  i := 0;
  while PAdrPtr^[i] <> nil do
  begin
    s.Add(inet_ntoa(PAdrPtr^[I]^));
    Inc(I);
  end;
end;


procedure QuickSendUDP(const h: string; const port: integer;
  var Data; const DataLen: integer);

var
  addr: sockaddr_in;
  sock: TSocket;

begin
  addr.sin_family := AF_INET;
  addr.sin_addr.S_addr := StrToAddr(h);
  addr.sin_port := htons(port);
  sock := Socket(AF_INET, SOCK_DGRAM, 0);
  if sock = INVALID_SOCKET then
    raise exception.create('Could not create socket');
  try
    if sendto(sock,Data,DataLen,0,addr,sizeof(addr)) = SOCKET_ERROR then
      raise exception.create('Could not send packet');
  finally
    closesocket(sock);
  end;
end;

constructor TQuickUDPServerThread.Create(const Suspended: boolean; const ListenPort: Word);
begin
  inherited Create(true);
  FListenPort := ListenPort;
  if not Suspended then
    Resume;
end;

procedure TQuickUDPServerThread.ShowError;
begin
  ShowMessage(ExceptMsg);
end;

procedure TQuickUDPServerThread.Execute;
begin
  try
    FreeOnTerminate := true;
    sock := Socket(AF_INET, SOCK_DGRAM, 0);
    if sock = INVALID_SOCKET then
      raise exception.create('Could not allocate a socket: Winsock error '+inttostr(WSAGetLastError));
    arg := 10000; // 10 seconds
    if setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,@arg,sizeof(arg)) = SOCKET_ERROR then
      raise exception.create('Could set socket timeout: Winsock error '+inttostr(WSAGetLastError));
    fillchar(listener,sizeof(listener),0);
    listener.sin_family := AF_INET;
    listener.sin_addr.S_addr := INADDR_ANY;
    listener.sin_port := htons(FListenPort);
    if bind(sock,listener,sizeof(sockaddr_in)) = SOCKET_ERROR then
      raise exception.create('Cannot bind to address: Winsock error '+inttostr(WSAGetLastError));
    while not Terminated do
      begin
        arg := sizeof(sockaddr_in);
        Req_Len := recvfrom(sock,Req,sizeof(Req),0,remote,arg);
        if Req_Len <> SOCKET_ERROR then
          DoRequest;
      end;
    closesocket(sock);
  except
    on e: Exception do
      begin
        ExceptMsg := e.Message;
        Synchronize(ShowError);
      end;
  end;
end;

initialization
  WSAStartup($0101,WSData);
finalization
  WSACleanup;
end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -