I am having troubles programming a TCP client/server using sockets. I've made a little programme that use the MSDN examples i found here : http://msdn.microsoft.com/en-us/library/bew39x2a%28v=vs.110%29.aspx but with a few modifications like a queue on the send function:
public void Send(String data)
{
// Wait for server connection
if (connectDone.WaitOne())
{
// If already sending data, add to the queue
// it will be sent by SendCallback method
if (_sending)
{
_queue.Enqueue(data);
}
else
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
_sending = true;
SocketHolder.BeginSend(byteData, 0, byteData.Length, 0, SendCallback, SocketHolder);
}
}
}
The data are read by the server via the readcallback function :
public void ReadCallback(IAsyncResult ar)
{
string content = string.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
// Check for end of message tag & raise event
content = state.sb.ToString();
if (content.IndexOf("</MetrixData>") > -1)
{
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}", content.Length, content);
OnMessageReceived(EventArgs.Empty, content);
state.sb = new StringBuilder(); // Clear the message from state object string builder
}
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, ReadCallback, state);
}
}
Well, now here is my problem : the whole point of my application is to send variable to a server at high frequency (up to 60 time per seconds for each variable). BUT, when i try to update very quickly my data, it seems the string builder of my state object doesn't have the time to clear properly as i reiceive multiple data at the same time within my OnMessageReceived function (which is a problem because i serialize every data i send so i end up with multiple root element in the message received by the server).
The whole project is available here if you want to have a closer look (not really sure my explanations are clear...)
Thank you in advance for your help & your time :)
EDIT : Sorry, i will try to give a beter explanation of my problem :p
Here is a message example sent & received correctly when i update a data solely.
<MetrixData>
<DataId>IntTest</DataId>
<Type>System.Int32</Type>
<Value TimeStamp="22/07/14 22:22:19">10</Value>
</MetrixData>
And here is what my server receive if i make multiple update of my data in a very short period of time.
<MetrixData>
<DataId>IntTest</DataId>
<Type>System.Int32</Type>
<Value TimeStamp="22/07/14 22:25:06">12</Value>
</MetrixData><MetrixData>
<DataId>IntTest</DataId>
<Type>System.Int32</Type>
<Value TimeStamp="22/07/14 22:25:06">13</Value>
</MetrixData><MetrixData>
<DataId>IntTest</DataId>
<Type>System.Int32</Type>
<Value TimeStamp="22/07/14 22:25:06">14</Value>
</MetrixData>
(can receive 2, 3... or up to 10 messages at the same time)
I can't figure out why my ReadCallback doesn't detect the end of the current message and doesn't reset the buffer which should be done by this sample of ReadCallBack
// Check for end of message tag & raise event
content = state.sb.ToString();
if (content.IndexOf("</MetrixData>") > -1)
{
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}", content.Length, content);
OnMessageReceived(EventArgs.Empty, content);
state.sb = new StringBuilder(); // Clear the message from state object string builder
}
NoDelayto switch off Nagle's algorithm. The rule is data will be sent in packets at most every 200 milliseconds. This is not an answer but just a comment because I didn't check all of your project's code and thus can't be sure it solves your problem."<root>" + content + "</root>". The processor will then have to handle all nested<MetrixData />elements in order.