B
Brian Rice
I have a socket application that is sending and receiving packets
asynchronously. It works great except, when I receive packets that are
larger than my receive buffer which then generate several EndReceive
calls... these calls seem to be sometimes coming out of order.
For example, the following is from my log file:
Connection at 5/1/2004 11:39:14 AM
SENT> ZZZ:1:FMZZZ:ID1234WAAAA:VR100:\0
RCVD> ZZZ:1:FMZZZ:SW24657:CNUS:TO480:TX113731X05012004EOCX OPR
RCVD> ACASHTESTSX:\0
Connection at 5/1/2004 11:39:32 AM
SENT> ZZZ:1:FMZZZ:ID1234WAAAA:VR100:\0
RCVD> ACASHTESTSX:\0
RCVD> ZZZ:1:FMZZZ:SW24657:CNUS:TO480:TX113748X05012004EOCX OPR
Is there any way I can manage this? Or something that would prevent
this from happening?
Thanks!
- Brian
Here is my test code:
using System;
using System.Net;
using System.Net.Sockets;
namespace UnitTest
{
/// <summary>
/// Summary description for SocketTest.
/// </summary>
public class SocketTest
{
public SocketTest()
{
}
protected Socket _socket = null;
public class SocketPacket
{
public byte[] Buffer = new Byte[100];
public Socket Socket;
public SocketPacket(Socket socket)
{
Socket = socket;
}
}
public void Stop()
{
_socket.Shutdown(SocketShutdown.Both);
_socket.Close();
}
public void Start(string ipAddress, int port)
{
// Create socket and connect
_socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,
ProtocolType.Tcp);
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(ipAddress),
port);
_socket.Connect(endPoint);
System.IO.StreamWriter sw;
sw = System.IO.File.AppendText("C:\\Connection.log");
sw.WriteLine("Connection at " + DateTime.Now.ToString());
sw.Close();
// set up a bunch of receive packets
for (int i=1;i<10;i++)
{
SocketPacket packet = new SocketPacket(_socket);
_socket.BeginReceive(
packet.Buffer, 0, packet.Buffer.Length,
SocketFlags.None,
new AsyncCallback(EndReceive),
packet
);
}
// send a message
SocketPacket packet2 = new SocketPacket(_socket);
packet2.Buffer = System.Text.Encoding.ASCII.GetBytes("FOL:1:FMFOL:IDONE-FOLWEXIT:VR100:\0");
WriteBufferToLog("SENT> ", packet2.Buffer);
_socket.BeginSend(
packet2.Buffer, 0, packet2.Buffer.Length,
SocketFlags.None,
new AsyncCallback(EndSend),
packet2
);
}
public void EndSend(IAsyncResult asyncResult)
{
SocketPacket packet = (SocketPacket)asyncResult.AsyncState;
packet.Socket.EndSend(asyncResult);
}
public void EndReceive(IAsyncResult asyncResult)
{
// we seem to get EndReceive's while disconnecting
// is there a way to drop these before we shutdown
// so EndReceive doesn't get called?
if (_socket == null)
return;
if (!_socket.Connected)
return;
SocketPacket packet = (SocketPacket)asyncResult.AsyncState;
packet.Socket.EndSend(asyncResult);
WriteBufferToLog("RCVD> ", packet.Buffer);
// put packet back on receive queue
_socket.BeginReceive(
packet.Buffer, 0, packet.Buffer.Length,
SocketFlags.None,
new AsyncCallback(EndReceive),
packet
);
}
public void WriteBufferToLog(string prefix, byte[] buffer)
{
System.IO.StreamWriter sw;
sw = System.IO.File.AppendText("C:\\Connection.log");
sw.WriteLine(prefix + GetString(buffer));
sw.Close();
}
public string GetString(byte[] buffer)
{
string result = "";
int index = 0;
while (index < buffer.Length && buffer[index] > 0)
{
char[] chars = new char[buffer.Length + 1];
System.Text.Decoder d = System.Text.Encoding.ASCII.GetDecoder();
int len = d.GetChars(buffer, index, buffer.Length - index, chars,
0);
string str = new System.String(chars);
int n = str.IndexOf("\0");
if (n >= 0)
str = str.Substring(0, n);
index += str.Length + 1;
if (index < buffer.Length)
result += str + @"\0";
else
result += str;
}
return result;
}
}
}
asynchronously. It works great except, when I receive packets that are
larger than my receive buffer which then generate several EndReceive
calls... these calls seem to be sometimes coming out of order.
For example, the following is from my log file:
Connection at 5/1/2004 11:39:14 AM
SENT> ZZZ:1:FMZZZ:ID1234WAAAA:VR100:\0
RCVD> ZZZ:1:FMZZZ:SW24657:CNUS:TO480:TX113731X05012004EOCX OPR
RCVD> ACASHTESTSX:\0
Connection at 5/1/2004 11:39:32 AM
SENT> ZZZ:1:FMZZZ:ID1234WAAAA:VR100:\0
RCVD> ACASHTESTSX:\0
RCVD> ZZZ:1:FMZZZ:SW24657:CNUS:TO480:TX113748X05012004EOCX OPR
Is there any way I can manage this? Or something that would prevent
this from happening?
Thanks!
- Brian
Here is my test code:
using System;
using System.Net;
using System.Net.Sockets;
namespace UnitTest
{
/// <summary>
/// Summary description for SocketTest.
/// </summary>
public class SocketTest
{
public SocketTest()
{
}
protected Socket _socket = null;
public class SocketPacket
{
public byte[] Buffer = new Byte[100];
public Socket Socket;
public SocketPacket(Socket socket)
{
Socket = socket;
}
}
public void Stop()
{
_socket.Shutdown(SocketShutdown.Both);
_socket.Close();
}
public void Start(string ipAddress, int port)
{
// Create socket and connect
_socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,
ProtocolType.Tcp);
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(ipAddress),
port);
_socket.Connect(endPoint);
System.IO.StreamWriter sw;
sw = System.IO.File.AppendText("C:\\Connection.log");
sw.WriteLine("Connection at " + DateTime.Now.ToString());
sw.Close();
// set up a bunch of receive packets
for (int i=1;i<10;i++)
{
SocketPacket packet = new SocketPacket(_socket);
_socket.BeginReceive(
packet.Buffer, 0, packet.Buffer.Length,
SocketFlags.None,
new AsyncCallback(EndReceive),
packet
);
}
// send a message
SocketPacket packet2 = new SocketPacket(_socket);
packet2.Buffer = System.Text.Encoding.ASCII.GetBytes("FOL:1:FMFOL:IDONE-FOLWEXIT:VR100:\0");
WriteBufferToLog("SENT> ", packet2.Buffer);
_socket.BeginSend(
packet2.Buffer, 0, packet2.Buffer.Length,
SocketFlags.None,
new AsyncCallback(EndSend),
packet2
);
}
public void EndSend(IAsyncResult asyncResult)
{
SocketPacket packet = (SocketPacket)asyncResult.AsyncState;
packet.Socket.EndSend(asyncResult);
}
public void EndReceive(IAsyncResult asyncResult)
{
// we seem to get EndReceive's while disconnecting
// is there a way to drop these before we shutdown
// so EndReceive doesn't get called?
if (_socket == null)
return;
if (!_socket.Connected)
return;
SocketPacket packet = (SocketPacket)asyncResult.AsyncState;
packet.Socket.EndSend(asyncResult);
WriteBufferToLog("RCVD> ", packet.Buffer);
// put packet back on receive queue
_socket.BeginReceive(
packet.Buffer, 0, packet.Buffer.Length,
SocketFlags.None,
new AsyncCallback(EndReceive),
packet
);
}
public void WriteBufferToLog(string prefix, byte[] buffer)
{
System.IO.StreamWriter sw;
sw = System.IO.File.AppendText("C:\\Connection.log");
sw.WriteLine(prefix + GetString(buffer));
sw.Close();
}
public string GetString(byte[] buffer)
{
string result = "";
int index = 0;
while (index < buffer.Length && buffer[index] > 0)
{
char[] chars = new char[buffer.Length + 1];
System.Text.Decoder d = System.Text.Encoding.ASCII.GetDecoder();
int len = d.GetChars(buffer, index, buffer.Length - index, chars,
0);
string str = new System.String(chars);
int n = str.IndexOf("\0");
if (n >= 0)
str = str.Substring(0, n);
index += str.Length + 1;
if (index < buffer.Length)
result += str + @"\0";
else
result += str;
}
return result;
}
}
}