Asynchronous socket woes

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance

From: Rick Elliott via .NET 247 (anonymous_at_dotnet247.com)
Date: 08/04/04


Date: Wed, 04 Aug 2004 05:06:01 -0700

I tried posting this issue last week, but it never showed up on the list. My apologies if I've created a duplicate.

Hello, there. I'm a relative newbie to .NET and certainly a greenhorn on the finer points of socket programming and I'm running into some trouble. I'm trying to create a class (no UI) that allows an application to communicate with a server by sending and receiving protocols (I guess you could term my class as a client since I'm not accepting connections, just establishing one to the server). In my class, I'm using asynchronous calls (i.e. BeginSend, EndSend, BeginReceive, EndReceive) to send and receive data since I don't want the application hanging while data is being sent/received.

I've established a connection successfully and can send and receive data. However, I appear to be receiving chunks of data out of order on occasion (i.e. I added a packet number to my buffer object that I use for the BeginReceive/EndReceive calls, and I get it back in a sequence similar to 1,2,3,4,6,5,7,9,8) which really screws up my app (it's not good to receive an XML document in a semi-chopped up fashion ;-). I'm quite sure I'm doing something goof, but I've been banging my head against the wall for the past two days trying to figure it out. Here's a quick rundown on what I'm using:
* Using TCP socket in Stream mode. The socket is blocking.
* Using 256 byte buffer to receive data. Have tried other sizes but hasn't made a difference that I can tell (I tried a one byte buffer for grins and it exhibits the same behavior, actually makes it easier to exhibit the problem, which makes sense).
* Converted to use NetworkStream instead of using Socket directly (use BeginRead/EndRead calls), but no luck. This is what I'm currently using.

Here are my send and receive methods, plus my socket and stream setup:

...
// Create new instance of socket
mSocket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
mSocket.Blocking=true;
...
// Create new instance of network stream for all socket communication
mStream=new NetworkStream(mSocket,System.IO.FileAccess.ReadWrite,false);
...
public void Send(string appId, string command, string data)
{
  try
  {
  // Construct the information to be sent to the server
  byte[] SendData = Encoding.Default.GetBytes(appId+mDelimiter+command+mDelimiter+data+mEOM.ToString());

  Console.WriteLine("Sending Data: {0}",appId+mDelimiter+command+mDelimiter+data+mEOM.ToString());

  // Start sending the data to the server
  mStream.BeginWrite(SendData,0,SendData.Length,mSendCallback,mStream);
  }
  catch (Exception e)
  {
  // TODO: Add exception handling to Send method
  Console.WriteLine(e.ToString());
  }
}

private void OnSend(IAsyncResult result)
{
  // Get the socket that sent the data
  NetworkStream SendStream=(NetworkStream) result.AsyncState;

  // Complete the send operation
  SendStream.EndWrite(result);

  // Start listening for data from the server
  Receive();
}

private void Receive()
{
  try
  {
  // Create object to receive the information from the server
  DataPacket ReceiveState=new DataPacket(mStream,mBufferSize);

  // Set the packet number
  ReceiveState.PacketNumber=++mPacketCount;

  // Start receiving information from the server
  mStream.BeginRead(ReceiveState.Buffer,0,mBufferSize,mReceiveCallback,ReceiveState);
  }
  catch (Exception e)
  {
  // TODO: Add exception handling to the Receive method
  Console.WriteLine(e.ToString());
  }
}

private void OnReceive(IAsyncResult result)
{
  try
  {
  // Get the object that contains the received data
  DataPacket ReceiveState=(DataPacket) result.AsyncState;

  // Get the stream that is receiving the data
  NetworkStream ReceiveStream=ReceiveState.Stream;

  // End the current receive operation
  ReceiveState.Length = ReceiveStream.EndRead(result);

  Console.WriteLine("Data Packet {0}: {1}",ReceiveState.PacketNumber,ReceiveState.ToString());

  if (ReceiveState.Length > 0)
  {
    // Make sure our call back is established
    if (mCallbackObject != null)
    {
    // Process the received message
    ProcessData(ReceiveState);
    }

  // Listen for more data
  Receive();
  }
  else
  {
  // Close the socket connection
  Close();
  }
  }
  catch (ObjectDisposedException e)
  {
  // Close the socket
  Close();
  }
}

Any thoughts on how I could be goofing this up would be happily accepted. I've scoured several sites and looked at several examples, but I can't see what I'm doing wrong. Hopefully it is something easy. If more source is required to help see the issue, I will happily send the class with the whole deal in it. Thanks.
--------------------------------
From: Rick Elliott

-----------------------
Posted by a user from .NET 247 (http://www.dotnet247.com/)

<Id>1D7NuB7tmUel+3NwSTnSTQ==</Id>



Relevant Pages

  • Re: How do I stop a Winsock from buffering characters?
    ... it's applied at the OS level to the socket. ... Stream s = client.GetStream; ... from the client code and have the server see it right away. ... first character of the client send. ...
    (microsoft.public.windowsce.embedded)
  • Concurrent reader/writer threads on single socket
    ... I have what I imagine is a well-known .Net networking problem, ... one dedicated to reading from the socket and the other one ... BinaryWriter writer = new BinaryWriter); ... the output stream would hold a separate buffer ...
    (microsoft.public.dotnet.general)
  • Re: std::cin and disabling canonical line processing (buffering)
    ... I believe I have found a couple of implementations of sockets in streams but ... > * create the streambufs, istream, and ostream around that socket ... >> I have a program that runs a command line interface on an embedded system. ... >> function is just given the stream pointers. ...
    (microsoft.public.vc.stl)
  • Re: Im having problems with cryptography and sockets, help
    ... If the sender does not send 8192 bytes, the call to Read is going to ... I am> using blocking sockets, so I am aware that if the socket does not have ... But I know that it does receive> the data, and still it blocks, not the NetworkStream, but the CryptoStream> used to decrypt the data. ... > NetworkStream stream = clienteTcp.GetStream;> // Crear el stream criptográfico ...
    (microsoft.public.dotnet.languages.csharp)
  • socket bug or not?
    ... This works fine, I at some point wrote a webservice to send msgs to my system, not using any twisted code, that sends a message to ... I discovered that it was because my webservice did not read the "<stream>" element sent by the server when it connected, when I added the code to read it, everything worked as expected. ... I tested the webservice to without the server to see if it had a problem, using netcat, and it does, so I wonder if there is a bug in the socket code or not. ...
    (comp.lang.python)