public SocketClient(SocketClientSettings theSocketClientSettings) { prefixHandler = new PrefixHandler(); messageHandler = new MessageHandler(); socketClientSettings = theSocketClientSettings; token = new DataHoldingUserToken(0, 0); }
public Int32 HandlePrefix(byte[] buffer, DataHoldingUserToken receiveSendToken, Int32 remainingBytesToProcess) { bool incomingTcpMessageIsReady = false; // Remember there is a receiveSendToken.receivedPrefixBytesDoneCount // variable, which allowed us to handle the prefix even when it // requires multiple receive ops. In the same way, we have a // receiveSendToken.receivedMessageBytesDoneCount variable, which // helps us handle message data, whether it requires one receive // operation or many. if (remainingBytesToProcess >= receiveSendToken.lengthOfCurrentIncomingMessage - receiveSendToken.receivedMessageBytesDoneCount) { // If we are inside this if-statement, then we got // the end of the message. In other words, // the total number of bytes we received for this message matched the // message length value that we got from the prefix. // Write/append the bytes received to the byte array in the // DataHolder object that we are using to store our data. receiveSendToken.dataReceived.Write(buffer, receiveSendToken.receiveMessageOffset, receiveSendToken.lengthOfCurrentIncomingMessage - receiveSendToken.receivedMessageBytesDoneCount); remainingBytesToProcess -= receiveSendToken.lengthOfCurrentIncomingMessage - receiveSendToken.receivedMessageBytesDoneCount; if (remainingBytesToProcess > 0) { receiveSendToken.receiveMessageOffset += receiveSendToken.lengthOfCurrentIncomingMessage - receiveSendToken.receivedMessageBytesDoneCount; } else { receiveSendToken.receiveMessageOffset = receiveSendToken.bufferOffsetReceive; } receiveSendToken.lengthOfCurrentIncomingMessage = ReadInt32(receiveSendToken.dataReceived.GetBuffer(), 2); receiveSendToken.currentMessageCompressed = (receiveSendToken.lengthOfCurrentIncomingMessage & 1 << 30) != 0; if (receiveSendToken.currentMessageCompressed) { receiveSendToken.lengthOfCurrentIncomingMessage ^= 1 << 30; } if (receiveSendToken.lengthOfCurrentIncomingMessage > 65535) { receiveSendToken.state = DataHoldingUserToken.State.Error; return(0); } receiveSendToken.state = DataHoldingUserToken.State.Content; receiveSendToken.receivedMessageBytesDoneCount = 0; return(remainingBytesToProcess); } else { // If we are inside this else-statement, then that means that we // need another receive op. We still haven't got the whole message, // even though we have examined all the data that was received. // Not a problem. In SocketListener.ProcessReceive we will just call // StartReceive to do another receive op to receive more data. receiveSendToken.dataReceived.Write(buffer, receiveSendToken.receiveMessageOffset, remainingBytesToProcess); receiveSendToken.receiveMessageOffset = receiveSendToken.bufferOffsetReceive; receiveSendToken.receivedMessageBytesDoneCount += remainingBytesToProcess; return(0); } }
/// <summary> /// If buffer still has data after call this function, it will return true. /// </summary> /// <param name="receiveSendEventArgs"></param> /// <param name="receiveSendToken"></param> /// <param name="remainingBytesToProcess"></param> /// <returns></returns> private bool ReceiveOneMessage(byte[] buffer, DataHoldingUserToken receiveSendToken, ref int remainingBytesToProcess) { // If we have not got all of the prefix then we need to work on it. // receivedPrefixBytesDoneCount tells us how many prefix bytes were // processed during previous receive ops which contained data for // this message. (In normal use, usually there will NOT have been any // previous receive ops here. So receivedPrefixBytesDoneCount would be 0.) if (receiveSendToken.state == DataHoldingUserToken.State.Prefix) { remainingBytesToProcess = prefixHandler.HandlePrefix(buffer, receiveSendToken, remainingBytesToProcess); if (remainingBytesToProcess == 0) { //Jump out of the method, since there is no more data. return(false); } } if (receiveSendToken.state == DataHoldingUserToken.State.Error) { StartDisconnect(); } // If we have processed the prefix, we can work on the message now. // We'll arrive here when we have received enough bytes to read // the first byte after the prefix. bool incomingTcpMessageIsReady = messageHandler.HandleMessage(buffer, receiveSendToken, ref remainingBytesToProcess); if (incomingTcpMessageIsReady) { // Process the data received, this function should use the data in dataReceived, and Deserialize the data // then the dataReceived will be reused to receive other data. //OnMessageRecieved(receiveSendToken.SessionId, receiveSendToken.dataReceived); byte[] b; int length = 0; if (receiveSendToken.currentMessageCompressed) { try { length = LZ4Codec.Decode32(receiveSendToken.dataReceived.GetBuffer(), 0, (int)receiveSendToken.dataReceived.Length, mDecodeBuffer, 0, mDecodeBuffer.Length, false); b = mDecodeBuffer; } catch (Exception ex) { Logger.Error("Message can not unwrap, this may caused by a hacker's attack." + ex.ToString()); b = null; } } else { b = receiveSendToken.dataReceived.GetBuffer(); length = (int)receiveSendToken.dataReceived.Length; } if (b != null) { using (var ms = new MemoryStream(b, 0, length)) { var message = SerializerUtility.Deserialize(ms); receiveSendToken.Reset(); if (message.Type == (int)MessageType.Ping) { latency = DateTime.Now - DateTime.FromBinary((long)message.ClientId); } else { if (MessageReceived != null) { MessageReceived(message); } } } } // continue to process another message which is not completed. if (remainingBytesToProcess > 0) { return(true); } return(false); } else { // Since we have NOT gotten enough bytes for the whole message, // we need to do another receive op. Reset some variables first. // All of the data that we receive in the next receive op will be // message. None of it will be prefix. So, we need to move the // receiveSendToken.receiveMessageOffset to the beginning of the // buffer space for this SAEA. receiveSendToken.receiveMessageOffset = receiveSendToken.bufferOffsetReceive; return(false); } }
public bool HandleMessage(byte[] buffer, DataHoldingUserToken receiveSendToken, ref Int32 remainingBytesToProcess) { bool incomingTcpMessageIsReady = false; //Create the array where we'll store the complete message, //if it has not been created on a previous receive op. if (receiveSendToken.receivedMessageBytesDoneCount == 0) { receiveSendToken.dataReceived.SetLength(receiveSendToken.lengthOfCurrentIncomingMessage); receiveSendToken.dataReceived.Seek(0, SeekOrigin.Begin); } // Remember there is a receiveSendToken.receivedPrefixBytesDoneCount // variable, which allowed us to handle the prefix even when it // requires multiple receive ops. In the same way, we have a // receiveSendToken.receivedMessageBytesDoneCount variable, which // helps us handle message data, whether it requires one receive // operation or many. if (remainingBytesToProcess >= receiveSendToken.lengthOfCurrentIncomingMessage - receiveSendToken.receivedMessageBytesDoneCount) { // If we are inside this if-statement, then we got // the end of the message. In other words, // the total number of bytes we received for this message matched the // message length value that we got from the prefix. // Write/append the bytes received to the byte array in the // DataHolder object that we are using to store our data. receiveSendToken.dataReceived.Write(buffer, receiveSendToken.receiveMessageOffset, receiveSendToken.lengthOfCurrentIncomingMessage - receiveSendToken.receivedMessageBytesDoneCount); incomingTcpMessageIsReady = true; remainingBytesToProcess -= receiveSendToken.lengthOfCurrentIncomingMessage - receiveSendToken.receivedMessageBytesDoneCount; if (remainingBytesToProcess > 0) { receiveSendToken.receiveMessageOffset += receiveSendToken.lengthOfCurrentIncomingMessage - receiveSendToken.receivedMessageBytesDoneCount; } else { receiveSendToken.receiveMessageOffset = receiveSendToken.bufferOffsetReceive; } } else { // If we are inside this else-statement, then that means that we // need another receive op. We still haven't got the whole message, // even though we have examined all the data that was received. // Not a problem. In SocketListener.ProcessReceive we will just call // StartReceive to do another receive op to receive more data. receiveSendToken.dataReceived.Write(buffer, receiveSendToken.receiveMessageOffset, remainingBytesToProcess); receiveSendToken.receiveMessageOffset = receiveSendToken.bufferOffsetReceive; receiveSendToken.receivedMessageBytesDoneCount += remainingBytesToProcess; remainingBytesToProcess = 0; } return(incomingTcpMessageIsReady); }