Delphi中的简单TCP连接超时包装器

时间:2014-09-20 13:40:24

标签: multithreading delphi sockets tcp winsock

我正在尝试创建一个支持超时参数的connect包装器。

主要功能应如下所示:

function ConnectToHost (Host : PAnsiChar; Port : Word; Timeout: DWORD): Integer;

我也希望尽可能简单,并将套接字保持在阻塞模式。

此外,我们的想法是使用纯Winsock API而不使用Indy组件或任何东西。


主函数应返回一个Integer,以获取有关所发生事件的其他信息。

我在想的是connect函数返回的返回值以及超时信息的其他值。


在main函数内部有一个线程负责连接,而main函数在给定的超时时间内等待线程。


现在我担心将主机和端口等数据传递给线程和内存泄漏。

我正在考虑将这些API用于超时操作:

  • CreateThread
  • WaitForSingleObject
  • GetExitCodeThread
  • TerminateThread

和使用winsock的TCP连接的这些API:

  • socket
  • htons
  • inet_addr
  • connect

如果考虑超时限制,安全connect包装器怎么样呢?

现在我似乎不知道如何才能做到这一点。任何帮助,将不胜感激。

1 个答案:

答案 0 :(得分:3)

尝试这样的事情:

type
  PConnectInfo = ^ConnectInfo;
  ConnectInfo = record
    Socket: TSocket;
    Addr: sockaddr_in;
    ErrCode: Integer;
  end;

function ConnectProc(Param : Pointer): DWORD; stdcall;
begin
  With PConnectInfo(Param)^ do
  begin
    if connect(Socket, PAddrInfo(@Addr), SizeOf(Addr)) = 0 then
      ErrCode := 0
    else
      ErrCode := WSAGetLastError;
  end;
  Result := 0;
end;

function ConnectToHost (Host : PAnsiChar; Port : Word; Timeout: DWORD): Integer;
var
  ci: ConnectInfo;
  H: THandle;
  tid: DWORD;
begin
  Result := 0;

  ZeroMemory(@ci, SizeOf(ci));

  ci.Socket := ...;

  ZeroMemory(@ci, SizeOf(ci));
  ci.Addr.sin_family := AF_INET;
  ci.Addr.sin_addr.s_addr := inet_addr(Host);
  ci.Addr.sin_port := htons(Port);

  if Timeout = INFINITE then
  begin
    ConnectProc(@ci);
  end else
  begin
    h := CreateThread(nil, 0, @ConnectProc, @ci, 0, @tid);
    if h = 0 then
    begin
      Result := GetLastError;
      Exit;
    end;

    case WaitForSingleObject(h, Timeout) of
      WAIT_FAILED: begin
        Result := GetLastError;
      end;
      WAIT_OBJECT_0: begin
        Result := ci.ErrCode;
      end;
      WAIT_TIMEOUT: begin
        Result := WSAETIMEDOUT;
      end;
    else
      Result := -1;
    end;

    CloseHandle(h);
  end;

  if Result <> 0 then
    closesocket(ci.Socket);
end;