2

好的,我正在使用 TClientSocket 类和线程与主机列表同时工作。一切都很好,但我开始注意到,一段时间后,所有线程都卡在了 ReceiveBuf 调用中......如果我打开 10 个线程,例如检查 100 个主机,它会开始很好,但一段时间后所有线程都会卡住,因为出于某种原因,某些主机无法很好地回答此 ReceiveBuf 呼叫...我尝试执行 ReceiveLength 并检查接收是否 > 0,以调用 ReceiveBuf,但仍然无法正常工作。我将在下面发布原始代码:

function Threads.ReceiveProtocolVersion;
var
   ProtocolVersion: array[0..11] of AnsiChar;
begin
 try
    MySocket.Socket.ReceiveBuf(ProtocolVersion, SizeOf(ProtocolVersion));
    Version:= AnsiString(ProtocolVersion);
   ...//continues but doesn't matter because many threads get stucked in the ReceiveBuf call...
 except
    Terminate; //we terminate thread if raise some exception..

好的,所以经过一些研究,我开始尝试这样做:

function Threads.ReceiveProtocolVersion;
var
   ProtocolVersion: array[0..11] of AnsiChar;
   SizeBuf: integer;
begin
 try
    SizeBuf:= MySocket.Socket.ReceiveLength;
    if SizeBuf > 0 then
     begin
       MySocket.Socket.ReceiveBuf(ProtocolVersion, SizeOf(ProtocolVersion));
       Version:= AnsiString(ProtocolVersion);
        ....
     end;
 except
    Terminate; //we terminate thread if raise some exception..

显然,它解决了线程卡在 ReceiveBuf 调用中的问题,但是由于某种未知的原因,没有(甚至那些正常工作的)线程进入“if SizeBuf > 0”。有什么帮助吗?

//编辑显示更多线程代码:: Thread.Execute 是这样的:

procedure MyThread.Execute;
begin
  while not(Terminated) do
    begin
      if SocketConnect then
        begin
          if ReceiveProtocolVersion then
           begin
              DoAuthentication;
            end;
         end;
          MySocket.Close;
          MySocket.Free;
    end;
    Terminate;
end;

SocketConnect 函数是:

function MyThread.SocketConnect: bool;
begin
  Result:= false;
  MySocket:= TClientSocket.Create(Nil);
  MySocket.Port:= StrToInt(Form1.Edit1.Text);
  MySocket.ClientType:= ctBlocking;
  MySocket.Host:= Host; //Host is a private variable for thread class
  try
    MySocket.Active:= true;
    if (MySocket.Socket.Connected = true) then
      Result:= true;
  except
    Terminate;
  end;
end;
4

1 回答 1

1

我使用 TWinSocketStream 解决了这个问题。像这样的东西:

function MyThread.CheckProtocol: bool;
var
  SockStream: TWinSocketStream;
  ProtocolVersion: array[0..11] of AnsiChar;
begin
 try
    SockStream := TWinSocketStream.Create(MySocket.Socket, 3000);
    SockStream.Read(ProtocolVersion, SizeOf(ProtocolVersion));
    RFBVer:= AnsiString(ProtocolVersion);
    ....

我读到使用阻塞模式套接字的正确方法是通过 TWinSocketStream 发送/接收数据: DocWiki Embarcadero

无论如何,感谢那些试图提供帮助的人!

于 2013-05-21T17:33:15.207 回答