Asynchronous socket data received in c#
The receive process, if you're using some socket service header,
needs to check the header, and continues to read bytes till all the
packet message is received. This process is executed in the read
callback:
private void BeginReadCallback(IAsyncResult ar)
{
...
byte[] received = null
byte[] rawBuffer = null;
byte[] connectionHeader = connection.Header;
readMessage.PacketOffSet += readBytes;
if ((connectionHeader != null) && (connectionHeader.Length > 0))
{
int headerSize = connectionHeader.Length + 2;
bool readPacket = false;
bool readSocket = false;
do
{
connection.LastAction = DateTime.Now;
if (readMessage.PacketOffSet > headerSize)
{
for (int i = 0; i < connectionHeader.Length; i++)
{
if (connectionHeader[i] != readMessage.PacketBuffer[i])
{
throw new BadHeaderException(
"Message header is different from Host header.");
}
}
int messageLength =
(readMessage.PacketBuffer[connectionHeader.Length] << 8) +
readMessage.PacketBuffer[connectionHeader.Length + 1];
if (messageLength > FMessageBufferSize)
{
throw new MessageLengthException("Message " +
"length is greater than Host maximum message length.");
}
if (messageLength == readMessage.PacketOffSet)
{
rawBuffer =
readMessage.GetRawBuffer(messageLength, headerSize);
readPacket = false;
readSocket = false;
}
else
{
if (messageLength < readMessage.PacketOffSet)
{
rawBuffer =
readMessage.GetRawBuffer(messageLength, headerSize);
rawBuffer = CryptUtils.DecryptData(connection,
ref rawBuffer, FMessageBufferSize);
readPacket = true;
readSocket = false;
received = new byte[rawBuffer.Length];
Array.Copy(rawBuffer, 0, received, 0,
rawBuffer.Length);
FireOnReceived(connection, received, false);
}
else
{
if (messageLength > readMessage.PacketOffSet)
{
if (messageLength > readMessage.PacketLength)
{
readMessage.Resize(messageLength);
}
readPacket = false;
readSocket = true;
}
}
}
}
else
{
if (readMessage.PacketRemaining < headerSize)
{
readMessage.Resize(readMessage.PacketLength + headerSize);
}
readPacket = false;
readSocket = true;
}
} while (readPacket);
if (readSocket)
{
...
.BeginReceive(readMessage.PacketBuffer, readMessage.PacketOffSet,
readMessage.PacketRemaining, SocketFlags.None, ...);
...
}
}
else
{
rawBuffer = readMessage.GetRawBuffer(readBytes, 0);
}
if (rawBuffer != null)
{
rawBuffer = CryptUtils.DecryptData(connection,
ref rawBuffer, FMessageBufferSize);
received = new byte[rawBuffer.Length];
Array.Copy(rawBuffer, 0, received, 0, rawBuffer.Length);
FireOnReceived(connection, received, true);
readMessage.Resize(FSocketBufferSize);
...
The read callback method first checks if the connection has some
header and, if not, just gets the raw buffer and continues. If the
connection has some header, the method needs to check the message header
against the socket service header. Before doing that, it checks if the
packet message length is greater than the connection header length, to
ensure that it can parse the total message length. If not, it reads some
bytes. After checking the header, the method parses the message length,
and checks with the packet length. If the length is equal, it gets the
raw buffer and terminates the loop. If the message length is less than
that of the packet message, we have the message plus some data. So, the
method gets the raw buffer and continues to read using the same
MessageBuffer
class. If the length of the message is greater than that of the packet
message, before reading some data, it just resizes the packet buffer to
the message size, ensuring enough room for more read bytes.
0 comments:
Post a Comment