在线程内使用非阻塞 TClientSocket

Use non-blocking TClientSocket inside a thread

这篇 Embarcadero 文章描述了在线程中使用阻塞套接字。如果我将套接字创建为 ctNonBlocking 并且只向套接字写入简单消息,我应该使用 TClientWinSocket.SendText:

// Inside TThread::Execute: Option 1
strMessage := 'Hello!';
mySocket.Socket.SendText(strMessage);

或者我应该创建一个 TWinSocketStream 并使用 Write:

// Inside TThread::Execute: Option 2
strMessage := 'Hello!';
stream := TWinSocketStream.Create(mySocket.Socket, 1000);
stream.Write(strMessage[1], Length(strMessage));

我发现我的应用程序在退出时抛出异常(在 DPR 文件中 Application.Run() 之后并且无法调试),如果我注释掉所有 TClientSocket 代码,该异常就会消失。

如果套接字处于非阻塞模式,则不能使用TWinSocketStream。如果套接字未处于阻塞模式,TWinSocketStream 的构造函数将引发异常。这在 documentation:

中说明

Use TWinSocketStream to read or write information over a blocking socket connection...

...

Note: TWinSocketStream does not work with non-blocking sockets.

TClientSocket 在非阻塞模式下在工作线程中工作正常(尽管阻塞模式是首选),前提是该线程具有消息循环。原因是因为在非阻塞模式下,TClientSocket创建了一个内部window并将其与套接字相关联。此 window 从 WinSock 接收消息以触发 TClientSocket 的事件。因此,必须在同一线程上下文中创建、使用和销毁非阻塞模式下的 TClientSocket。不要跨线程边界访问它。

TClientSocket在阻塞模式下没有这个限制。