Here is an example of ReceiveCallback from MSDN.

 int bytesRecv = clientSocket.EndReceive(result); if (bytesRecv > 0) { clientSocket.BeginReceive(ci.Buffer, 0, ci.Buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), ci); } else { Console.WriteLine("Response"); } 

Suppose the client-side buffer size is 16 bytes. If I send from the server side, let's say 32 bytes, then the callback executes only two times by accepting 16 + 16 bytes. In this regard, the check bytesRecv = 0 does not work, and Console.WriteLine("") does not work, because The third time the callback does not start. What am I doing wrong?

  • And why do you use outdated BeginReceive / EndReceive? Why not async? - VladD
  • And the number of received bytes is determined not by (only) the size of the client's buffer, but by a million factors along the road between them. - VladD
  • I use outdated functions because regarding sockets on the Internet, I found only a mention of them. async I understand it applies generally to asynchronous functions? Just could not use. I will dig in this direction. - Alberto
  • Here there is a little on the topic: ru.stackoverflow.com/a/418010/10105 - VladD
  • one
    ReadAsync does not know that there will be no more data, and can’t find out if you don’t tell it. Therefore, when transmitting data through a socket, you have to invent a protocol in which you first report the length of the message, and then transmit the message itself. - VladD

3 answers 3

An example on MSDN implies that after sending the data, the other party will close the outgoing stream:

 socket.Shutdown(SocketShutdown.Send); 

In this case, the receiver, when attempting to read, reads zero bytes from the socket.

Such a mode of operation - “send data, close outgoing stream, receive data” - is the easiest for TCP protocol and historically first used. Therefore, most of the examples of working with sockets are written under a similar protocol.

If you need to keep the connection established - then you need to think up your own way of determining the boundaries of the message. This can be either a special message end marker, or an explicit length transfer before the message itself.

For example, the HTTP protocol uses a combined approach — the header block ends with two line feeds, and the data block (called the content body in HTTP) is exactly Content-Length bytes long. If the Content-Length header is not specified, the data block ends by closing the socket.

    For the third time, he continues to wait for data from the client. How does he know how much data you sent him? Condition

     if (bytesRecv > 0) ... else ... 

    will work if communication with the client is interrupted.

      See another answer for an example of client-server interaction . There, each client receives a response from the server, and then displays it on the console. Moreover, the implementation is such that after receiving the end-of-line character \n client stops receiving data already.

      As I understand it, you need about the same thing, but instead of outputting to the console, you need to accumulate data, and therefore have to do something with it.

      You can transmit the length at the very beginning, and then wait until all the characters come (we know the length). This way you can get rid of the special character.