开发者

Program freeze if the buffer allocated for TTCPClient.ReceiveBuf has exact size of return data packet

I am using Delphi's TTCPClient in unit sockets.pas to connect to a TCP service.

When I attempt to receive the response from the TCP service, I code as follow:

var gap: integer;
    T: TTCPClient;
    B: TBytes;
    i: integer;
begin
  ...
  gap := 10;
  SetLength(B, gap);
  i := 0;

  repeat
    i := T.ReceiveBuf(B[i], gap);
    if (i > 0) and (i < gap) then begin
      SetLength(B, Length(B) - (gap - i));
      Break;开发者_如何学C
    end else if (i > 0) then begin
      i := Length(B);
      SetLength(B, i + gap);
    end;
  until i = 0;
  ...
end;

I use an integer variable gap to control the buffer size read from socket. In this example, the gap is 10. The program will run without any problem if the receive size is not multiplier of gap (10). e.g. 4, 15, 29.

However, the program will freeze in ReceiveBuf if the the buffer in socket is multiplier of 10. e.g.: 10, 20, 30.

How may I coding with TTCPClient to make it work for any buffer size returned and my program won't freeze in half way?

I am using bmBlocking mode for this client socket.

Thank you.


Always check the result of ReceiveBuf. If an error occurs the result will be SOCKET_ERROR (which is declared in WinSock as -1). Your code doesn't handle this case and will continue executing the loop.

You can call WSAGetLastError to determine the specific error code. For example, the server might close the connection after sending all its data, which would be indicated by the error code WSAECONNRESET.


Since you are using blocking socket, calling ReceiveBuf when there is nothing to receive will hang until something is written on the socket.

If you receive 10 bytes, and read by 10 bytes chunks, after your first read, you did read 10 bytes, so it doesn't fit the condition (i > 0) and (i < gap) but it does fit (i > 0), so you go in for a 2nd read on an empty socket, and since the socket is blocking, you hang there until another packet is received.

Now, I don't have much experience with blocking sockets... but I'd guess using T.ReceiveLength = 0 as loop condition instead of (i = 0) might do the trick.


I cannot duplicate your problem with a simple test case. I'd guess, the problem is, you're not closing the connection on the sending side after the data has been sent, thus leaving the receiving side blocked waiting data as Ken's answer say.


Use raw socket call to find out any available data to be read if recv(your socket, nil, 0, MSG_PEEK) > 0 then ...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜