Reputation: 41
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, theReceive()
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 usingSocket.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
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 ofReceive()
.
Correct.
So I think I should call
recvToCnt()
instead ofReceive()
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 withReceive()
.
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
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 ofReceive()
.
Yes.
So I think I should call
recvToCnt()
instead ofReceive()
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 toReceive()
.
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