I've noticed what appears to be a bug in the Socket.Receive method in the 1.1
Framework. Specifically, when talking between sockets on the same machine,
the Receive method appears to ignore anything after a newline. For example,
here is a snippet of server code listening on all local addresses:
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 8000);
Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp);
newsock.Bind(ipep);
newsock.Listen(10);
while (true)
{
try
{
// Wait for a connection request
Socket client = newsock.Accept();
// more code to handle each connection on separate thread, etc
}
}
and on the client side,
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8000);
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp);
Server.Connect(ipep);
etc.
These two apps will talk to each other on port 8000 without apparent
problems. If, however, a line of data is sent such as the following:
sent = server.Send(Encoding.ASCII.GetBytes("This is a \n line of data\r\n"));
then all bytes will be sent to the server app's socket, yet the
Socket.Receive call on the server end will only return up to the \n from the
local buffer. In other words it will only receive "This is a \n". If the
server app is written to wait for a full line of data terminated with \r\n
then it will hang indefinitely. This does *not* happen if the client app is
on a remote machine, only if it is running on the same machine as the server
app. This happens whether 127.0.0.1 is used or another IP on the local
machine.
David Browne - 30 Aug 2005 19:25 GMT
> I've noticed what appears to be a bug in the Socket.Receive method in the
> 1.1
[quoted text clipped - 44 lines]
> app. This happens whether 127.0.0.1 is used or another IP on the local
> machine.
You are probably assuming that Socket.Receive will actually read as many
bytes as you ask for. It won't. If data is available Receive will return
immediately with some, but not necessarily all of the data.
From
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlr
fsystemnetsocketssocketclassreceivetopic1.asp
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.
So whether you get back all the data in one or multiple calls depends on
variable stuff in the TCP implementation. In short, Socket.Read must ALWAYS
be called in a loop. You cannot assume that a single call will return the
whole message. Doing so introduces a spratic bug into your code.
David
Pete R - 30 Aug 2005 20:52 GMT
Hi David,
I am well aware of the possibility of not getting all the data in one shot,
hence all Receive calls are of the form:
while (bufferString.IndexOf("\r\n") == -1)
{
buffer = new byte[4096];
recv = sock.Receive(buffer);
bufferString += Encoding.ASCII.GetString(buffer, 0, recv);
}
which waits until it has a full line no matter how long it takes. As I said
the same compiled executables consistently work as expected if they are on
different machines, just not on the same machine.
> > I've noticed what appears to be a bug in the Socket.Receive method in the
> > 1.1
[quoted text clipped - 60 lines]
>
> David
William Stacey [MVP] - 30 Aug 2005 20:56 GMT
Most true. I also noticed this more on same box as the thread switch
between send and receive so the recieve is more "chunky". I have even got 1
byte on receive many times. So the loop is *required as you state.

Signature
William Stacey [MVP]
>> I've noticed what appears to be a bug in the Socket.Receive method in the
>> 1.1
[quoted text clipped - 64 lines]
>
> David
Pete R - 30 Aug 2005 21:23 GMT
As mentioned, I always use a loop. It just hangs until the socket itself
times out, data after the newline just never gets read.
> Most true. I also noticed this more on same box as the thread switch
> between send and receive so the recieve is more "chunky". I have even got 1
[quoted text clipped - 68 lines]
> >
> > David
Pete R - 31 Aug 2005 00:21 GMT
Solution found, it is not a bug in Socket.Receive(), the problem was Symantec
AntiVirus! One of the local ports I was testing proxying information for was
port 25 (SMTP) which is apparently intercepted (badly) by the antivirus
software, and this is where \n is taken as \r\n if and only if done on the
local machine. Talk about your hair-pulling debugging session.
> Most true. I also noticed this more on same box as the thread switch
> between send and receive so the recieve is more "chunky". I have even got 1
[quoted text clipped - 68 lines]
> >
> > David
William Stacey [MVP] - 31 Aug 2005 02:31 GMT
:-)

Signature
William Stacey [MVP]
> Solution found, it is not a bug in Socket.Receive(), the problem was
> Symantec
[quoted text clipped - 85 lines]
>> >
>> > David