Socket Server Problems

  • Thread starter Thread starter Pete Davis
  • Start date Start date
P

Pete Davis

I'm trying to do async socket IO in a socket server in C# and I'm having
trouble on the receive side of things.

I've tried variations of the code below and I just can't seem to get it to
work. I think my _receiveEvent.Set() calls may be misplaced among other
things. EndReceive() gets called when the first message is sent.

What I want it to do is to continue to receive until the entire message has
arrived. I'm not really sure how to accomplish that. Once a full message has
arrived, I want to process the message (which generally involves a reply)
and then continue receiving.

Thanks for any help anyone can provide.

Pete Davis


private void CommunicationThread()
{
Monitor.Enter(_socketStates);
SocketState sockState = (SocketState) _socketStates[Thread.CurrentThread];
sockState.Connected = true;
Monitor.Exit(_socketStates);

try
{
_receiveEvent.Reset();
sockState.RemoteSocket.BeginReceive(sockState.ReceiveBuffer, 0,
SocketState.BufferSize, 0, new AsyncCallback(this.ReadCallback), sockState);
_receiveEvent.WaitOne();
}
catch(SocketException se)
{
sockState.Connected = false;
LogException(se);
}
catch(System.Exception ex)
{
sockState.Connected = false;
LogException(ex);
}
return;
}

private void ReadCallback(IAsyncResult asyncResult)
{
SocketState socketState = (SocketState) asyncResult.AsyncState;
int bytesRead = 0;
try
{
bytesRead = socketState.RemoteSocket.EndReceive(asyncResult);
Debug.WriteLine("SocketServer.ReadCallback: EndReceive completed");
}
catch (SocketException se)
{
// Likely the socket timed out.
LogException(se);
_receiveEvent.Set();
return;
}

Debug.WriteLine(String.Format("SocketServer.ReadCallback: End receive with
{0} bytes", bytesRead));
// Append new data until all data received
if (bytesRead > 0)
{
socketState.DataReceived = bytesRead;
socketState.BufferUpdate();
sockState.RemoteSocket.BeginReceive(socketState.ReceiveBuffer, 0,
SocketState.BufferSize, 0, new AsyncCallback(this.ReadCallback),
socketState);
_receiveEvent.Set();
return;
}
// All data received. Handle message
else
{
HandleMessage(socketState);
}
_receiveEvent.Set();
}
 
Pete Davis said:
What I want it to do is to continue to receive until the entire message
has arrived. I'm not really sure how to accomplish that. Once a full
message has arrived, I want to process the message (which generally
involves a reply) and then continue receiving.

Is there a reason is has to be non blocking? Blocking is a lot cleaner
implementation and unless you are writing a server for a 750+ concurrent
connections or so you probably wont see ANY difference in performance.
 
Actually, eventually, it may need to scale up to this. That might be overly
optimistic of me, but that is the plan.

Pete
 
I am assuming that:

1) The server will gracefully close the connection when it has finished
sending the data.
2) signalling the _receiveEvent() will cause your read loop to quit.

That being the case, it seems that your receive loop is terminating
prematurely:

if (bytesRead > 0)
{
socketState.DataReceived = bytesRead;
socketState.BufferUpdate();
sockState.RemoteSocket.BeginReceive(socketState.ReceiveBuffer, 0,
SocketState.BufferSize, 0, new AsyncCallback(this.ReadCallback),
socketState);
_receiveEvent.Set(); <<<<<< ===================
return;
}
// All data received. Handle message
else
{
HandleMessage(socketState);
}
_receiveEvent.Set();
}

In the above snippet, you shold comment out the _receiveEvent.Set() call
after claling beginreceive(). That will let the app continue receiveing
until it gets a zero byte packet (which means the peer closed connection
gracefully)
--
Remove "user" from the email address to reply to the author.

This posting is provided "AS IS" with no warranties, and confers no rights

Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm




Pete Davis said:
I'm trying to do async socket IO in a socket server in C# and I'm having
trouble on the receive side of things.

I've tried variations of the code below and I just can't seem to get it to
work. I think my _receiveEvent.Set() calls may be misplaced among other
things. EndReceive() gets called when the first message is sent.

What I want it to do is to continue to receive until the entire message has
arrived. I'm not really sure how to accomplish that. Once a full message has
arrived, I want to process the message (which generally involves a reply)
and then continue receiving.

Thanks for any help anyone can provide.

Pete Davis


private void CommunicationThread()
{
Monitor.Enter(_socketStates);
SocketState sockState = (SocketState) _socketStates[Thread.CurrentThread];
sockState.Connected = true;
Monitor.Exit(_socketStates);

try
{
_receiveEvent.Reset();
sockState.RemoteSocket.BeginReceive(sockState.ReceiveBuffer, 0,
SocketState.BufferSize, 0, new AsyncCallback(this.ReadCallback), sockState);
_receiveEvent.WaitOne();
}
catch(SocketException se)
{
sockState.Connected = false;
LogException(se);
}
catch(System.Exception ex)
{
sockState.Connected = false;
LogException(ex);
}
return;
}

private void ReadCallback(IAsyncResult asyncResult)
{
SocketState socketState = (SocketState) asyncResult.AsyncState;
int bytesRead = 0;
try
{
bytesRead = socketState.RemoteSocket.EndReceive(asyncResult);
Debug.WriteLine("SocketServer.ReadCallback: EndReceive completed");
}
catch (SocketException se)
{
// Likely the socket timed out.
LogException(se);
_receiveEvent.Set();
return;
}

Debug.WriteLine(String.Format("SocketServer.ReadCallback: End receive with
{0} bytes", bytesRead));
// Append new data until all data received
if (bytesRead > 0)
{
socketState.DataReceived = bytesRead;
socketState.BufferUpdate();
sockState.RemoteSocket.BeginReceive(socketState.ReceiveBuffer, 0,
SocketState.BufferSize, 0, new AsyncCallback(this.ReadCallback),
socketState);
_receiveEvent.Set();
return;
}
// All data received. Handle message
else
{
HandleMessage(socketState);
}
_receiveEvent.Set();
}
 
Pete Davis said:
Actually, eventually, it may need to scale up to this. That might be overly
optimistic of me, but that is the plan.

You need to be very careful about serialization effects if you use non
blocking.
 
Back
Top