Lucavin
Lucavin

Reputation: 41

is this the right way to call socket Send/Receive

My discussion is based on connected TCP, blocking sockets, synchronization.

Firstly about Receive(), MSDN says:

If no data is available for reading, the Receive() method will block until data is available.If you are using a connection-oriented Socket, the Receive() method will read as much data as is available up to the size of the buffer.

The emphasis on blocking made me misunderstand this passage. Later I did experiments and reached the following conclusions: If I want to accept 10 bytes, but only 6 bytes are readable in the socket cache, calling Receive() once does not block until 10 bytes are readable. Only to return, but as much as possible to read the now readable byte, that is, 6 bytes will be returned, so the actual number of bytes read is represented by the return value of Receive(). So I think I should call recvToCnt() instead of Receive() if I want to exactly receive the specified number of bytes.

private int recvToCnt(Socket socket, byte[] buf, int beginIndex, int cnt)
{
   if (buf.Length < beginIndex + cnt)
      return 0;

   int realCnt = 0;
   while (realCnt < cnt)
   {
      realCnt += socket.Receive(buf, beginIndex + realCnt, cnt - realCnt, SocketFlags.None);
   }
   return realCnt;
}

Then, let's see Send(). MSDN says:

If you are using a connection-oriented protocol, Send() will block until all of the bytes in the buffer are sent, unless a time-out was set by using Socket.SendTimeout().

I doubt the accuracy of this description, because Send() also has a return value, I guess it should have a similar blocking concept to Receive(). So I guess I should use sendToCnt() instead of sending if I want to make sure that the specified number of bytes is sent into the socket cache:

private int sendToCnt(Socket socket, byte[] buf, int beginIndex, int cnt)
{
   if (buf.Length < beginIndex + cnt)
      return 0;

   int realCnt = 0;
   while (realCnt < cnt)
   {
      realCnt += socket.Send(buf, beginIndex + realCnt, cnt - realCnt, SocketFlags.None);
   }
   return realCnt;
}

Is my idea correct? Any other idea?

Upvotes: 0

Views: 136

Answers (2)

user207421
user207421

Reputation: 310980

If I want to accept 10 bytes, but only 6 bytes are readable in the socket cache,

The socket receive buffer.

... calling Receive() once does not block until 10 bytes are readable. Only to return, but as much as possible to read the now readable byte, that is, 6 bytes will be returned, so the actual number of bytes read is represented by the return value of Receive().

Correct.

So I think I should call recvToCnt() instead of Receive() if I want exactly receive specify bytes.

You should certainly call Receive() in a loop until you have all the data you are expecting, or an error or end of stream occurs, but the code you posted ignores errors and end of stream completely, which is not acceptable. You need to fix that.

Then, let's see Send(). ... I doubt the accuracy of this description,

Don't. It is correct, in blocking mode.

because Send() also has a return value, I guess it should have similar blocking concept with Receive().

No. The return value becomes significant in non-blocking mode. In blocking mode it behaves as described.

So I guess I should use sendToCnt() instead of sending if I want to make sure that the specified number of bytes is sent into the socket cache

The socket send buffer, and no, and again the code you posted ignores errors, which once again is unacceptable.

Upvotes: 1

Remy Lebeau
Remy Lebeau

Reputation: 597166

If I want to accept 10 bytes, but only 6 bytes are readable in the socket cache, calling Receive() once does not block until 10 bytes are readable. Only to return, but as much as possible to read the now readable byte, that is, 6 bytes will be returned, so the actual number of bytes read is represented by the return value of Receive().

Yes.

So I think I should call recvToCnt() instead of Receive() if I want to exactly receive the specified number of bytes.

Yes.

I doubt the accuracy of this description, because Send() also has a return value, I guess it should have a similar blocking concept to Receive().

Yes. It can return fewer bytes than requested, if the socket's kernel buffer has enough space for at least 1 byte but does not have enough space for all of the bytes you are sending.

So I guess I should use sendToCnt() instead of sending if I want to make sure that the specified number of bytes is sent into the socket cache:

Yes.

Upvotes: 1

Related Questions