这是调用套接字的正确方法吗Send/Receive

is this the right way to call socket Send/Receive

我的讨论基于连接的 TCP、阻塞套接字、同步。

首先关于 Receive(),MSDN 说:

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.

强调阻塞让我对这段话产生了误解。后来做了实验,得出如下结论:如果我想接受10个字节,但是socket缓存中只有6个字节可读,调用一次Receive()直到10个字节可读才阻塞。只读到return,但尽可能读到现在可读的字节,即6个字节会被returned,所以实际读到的字节数用return表示Receive() 的值。所以我认为如果我想准确接收指定数量的字节,我应该调用 recvToCnt() 而不是 Receive()

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;
}

然后,让我们看看Send()。 MSDN 说:

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().

我怀疑这个描述的准确性,因为Send()也有一个return值,我猜它应该和Receive()有类似的阻塞概念。所以我想如果我想确保将指定数量的字节发送到套接字缓存中,我应该使用 sendToCnt() 而不是发送:

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;
}

我的想法对吗?还有其他想法吗?

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 exactly receive specify bytes.

你当然应该在循环中调用 Receive() 直到你拥有所有你期望的数据,或者发生错误或流结束,但是你发布的代码完全忽略了错误和流结束,这是不能接受的。你需要解决这个问题。

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

不要。没错,是阻塞模式。

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

没有。 return 值在非阻塞模式下变得很重要。在阻塞模式下,它的行为与描述的一样。

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

套接字发送缓冲区,没有,而且您发布的代码再次忽略了错误,这再次是不可接受的。

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.

是的。

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().

是的。它 可以 return 比请求的字节少,如果套接字的内核缓冲区有足够的 space 用于 至少 1 字节但是没有足够的 space 供您发送的 所有 个字节。

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:

是的。