Sockets starts to slow down and not respond - c#

i am developing a server (with c#) and a client (with flash, actionscript 3.0) application. Server sends data (datas are arround 90 bytes) to clients continuously and clients behave according to data they received (data is json formatted)
for a while, everything works as expected but after some time passed, clients start to receive messages laggy. they keep waiting for some time and then they behave according to last message (some messages lost). after some time passed clients starts to wait and process all the messages at the same time. I could not figured out what causing this. My network condition is stable.
here is some part of my c# code, sending message:
public void Send(byte[] buffer)
{
if (ClientSocket != null && ClientSocket.Connected)
{
ClientSocket.BeginSend(buffer, 0, buffer.Length, 0, WriteCallback, ClientSocket);
}
}
private void WriteCallback(IAsyncResult result)
{
//
}
and some part of my client, receiving message (actionscript)
socket.addEventListener(ProgressEvent.SOCKET_DATA, onResponse);
function onResponse(e:ProgressEvent):void {
trace(socket.bytesAvailable);
if(socket.bytesAvailable > 0) {
try
{
var serverResponse:String = socket.readUTFBytes(socket.bytesAvailable);
....
I hope i could explain my problem. How should i optimize my code? What can be causing lags. Thanks.

You really need to give more detail as to how you're setting up the socket (is it TCP or UDP?)
Assuming it's a TCP socket, then it would appear that your client relies on each receive call returning the same number of bytes that were sent by the server's Send() call. This is however not the case, and could well be the cause of your issues if a message is only being partially received on the client, or multiple messages are received at once.
For example, the server may send a 90 byte message in a single call, but your client may receive it in one 90-byte receive, or two 45-byte chunks, or even 90 x 1-byte chunks, or anything in between. Multiple messages sent by the server may also be partially combined when received by the client. E.g. two 90-byte messages may be received in a single 180-byte chunk, or a 150-byte and a 30-byte chunk, etc. etc.
You need therefore to provide some kind of framing on your messages so that when the stream of data is received by the client, it can be reliably reconstructed into individual messages.
The most basic framing mechanism would be to prefix each message sent with a fixed-length field indicating the message size. you may be able to get away with a single byte if you can guarantee that your messages will never be > 255 bytes long, which will simplify the receiving code.
On the client side, you first need to receive the length prefix, and then read up to that many bytes off the socket to construct the message data. If you receive fewer than the required number of bytes, your receiving code must wait for more data (appending it to the partially-received message when it is eventually received) until it has a complete message of the.
Once the full message is received it can be processed as you are currently.
Unfortunately I don't know ActionScript, so can't give you an example of the client-side code, but here's how you might write the server and client framing in C#:
Server side:
public void SendMessage(string message)
{
var data = Encoding.UTF8.GetBytes(message);
if (data.Length > byte.MaxValue) throw new Exception("Data exceeds maximum size");
var bufferList = new[]
{
new ArraySegment<byte>(new[] {(byte) data.Length}),
new ArraySegment<byte>(data)
};
ClientSocket.Send(bufferList);
}
Client side:
public string ReadMessage()
{
var header = new byte[1];
// Read the header indicating the data length
var bytesRead = ServerSocket.Receive(header);
if (bytesRead > 0)
{
var dataLength = header[0];
// If the message size is zero, return an empty string
if (dataLength == 0) return string.Empty;
var buffer = new byte[dataLength];
var position = 0;
while ((bytesRead = ServerSocket.Receive(buffer, position, buffer.Length - position, SocketFlags.None)) > 0)
{
// Advance the position by the number of bytes read
position += bytesRead;
// If there's still more data to read before we have a full message, call Receive again
if (position < buffer.Length) continue;
// We have a complete message - return it.
return Encoding.UTF8.GetString(buffer);
}
}
// If Receive returns 0, the socket has been closed, so return null to indicate this.
return null;
}

Related

Socket tcp c# how to clear input buffer?

I'm writing an application for windows phone and I need to communicate with a server and transmit data. The SERVER is written in C++ and I cannot modify it. The CLIENT is what I have to write. The Server is designed such that the client connect to it and transmit data. The connection remains open for all the transmission. By writing my code in C# I am able to receive data from the server but after the first receive, the data that I read in the buffer are alway the same. So I need a way to flush the input buffer so I can receive the new data (data are sent continuously). I'm using the class defined in here:
http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202858%28v=vs.105%29.aspx
thanks a lot !!
I used this code for Receiving in the SocketClient.cs :
public string Receive()
{
string response = "Operation Timeout";
// We are receiving over an established socket connection
if (_socket != null)
{
// Create SocketAsyncEventArgs context object
SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
socketEventArg.RemoteEndPoint = _socket.RemoteEndPoint;
// Setup the buffer to receive the data
socketEventArg.SetBuffer(new Byte[MAX_BUFFER_SIZE], 0, MAX_BUFFER_SIZE);
// Inline event handler for the Completed event.
// Note: This even handler was implemented inline in order to make
// this method self-contained.
socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
// *********************************************
// THIS part of the code was added to receive
// a vector of 3 double
Double[] OdomD = new Double[3];
for (int i = 0; i < 3; i++)
{
OdomD[i] = BitConverter.ToDouble(e.Buffer, 8 * i);
}
// *********************************************
}
else
{
response = e.SocketError.ToString();
}
_clientDone.Set();
});
// Sets the state of the event to nonsignaled, causing threads to block
_clientDone.Reset();
// Make an asynchronous Receive request over the socket
_socket.ReceiveAsync(socketEventArg);
// Block the UI thread for a maximum of TIMEOUT_MILLISECONDS milliseconds.
// If no response comes back within this time then proceed
_clientDone.WaitOne(TIMEOUT_MILLISECONDS);
}
else
{
response = "Socket is not initialized";
}
return response;
}
The Connect() method is exactly the same reported in the link above. So when the application start, the Connect() method is called as follow:
SocketClient client = new SocketClient();
// Attempt to connect to server for receiving data
Log(String.Format("Connecting to server '{0}' over port {1} (data) ...", txtRemoteHost.Text, 4444), true);
result = client.Connect(txtRemoteHost.Text, 4444);
Log(result, false);
That is done just once at the beginning, then I need receive this array of 3 double that is updated every second. So I use:
Log("Requesting Receive ...", true);
result = client.Receive();
Log(result, false);
The problem is that also if I debug the code and stop the execution inside Receive(), I always read the same value, that is the first value sent by the server. What I'm expecting is that every time I call client.Receive(), I get the new value, but this is not appening.
I had a similar problem by writing the same client in Matlab environment. I solved the problem by using the function flushinput(t) before to read the input buffer. In this way I was able to read always the last data sent by the server. I'm lookin for a function similar to that one ..
The size of the input buffer is fixed equal to the data that I'm expecting to receive, in that case is 24 bytes ( 3* sizeof(double) ) ..
Thanks a lot for you time !!
oleksii is right, you should call client.Receive() in a loop. You can choose to start a thread that covers the receive section of your code. Also note that client.Receive() will keep trying to receive from the buffer, and it will get stuck if there is no data available.
The main question was **how to clear the input buffer? ** or am I wrong?=!
Nevertheless; since you don't have a fixed buffer denoted as seen from you posted code and receive it via the SocketAsyncEventArgs, you could clear it with:
Array.Clear(e.Buffer, 0, e.Buffer.Length);

c# async sockets, read all buffer

I have a client that will send a lots of data to server from different threads.
The packet uses the following format:
PACKET_ID
CONTENT
END_OF_PACKET_INDICATOR
I have the following onDataRecieved function:
public void OnDataReceived(IAsyncResult asyn)
{
SocketPacket socketData = (SocketPacket)asyn.AsyncState;
int iRx = 0;
iRx = socketData.m_currentSocket.EndReceive(asyn);
char[] chars = new char[iRx + 1];
System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
int charLen = d.GetChars(socketData.dataBuffer, 0, iRx, chars, 0);
MessageBox.Show("Incoming data: " + socketData.dataBuffer.Length.ToString() + " from socket(" + socketData.socket_id + ")");
char[] PACKET_END_IDENTIFIER = { (char)2, (char)1, (char)2, (char)1 };
for (int i = 0; i < iRx; i++)
{
GLOBAL_BUFFER.Add(chars[iRx]);
}
if (PacketEndReached(chars, PACKET_END_IDENTIFIER))
{
// done reading the data
PROCESS_PACKET(GLOBAL_BUFFER);
}
WaitForData(socketData.m_currentSocket, socketData.socket_id);
}
My socket buffer size is set to 100. If I send 1000 bytes, they would be split up in 10 chunks and onDataRecieved would get triggered 10 times.
All I need to do is keep reading the data into buffer for each individual packet sent my client until PacketEndReached gets triggered
then pass the buffer to another function that will process the data.
If I define a GLOBAL_BUFFER for storing incoming data, then if client sends data from multiple threads, wouldn't the data get mixed up? I need a way to read all the data for each individual packet sent my client.
Thanks!
UPDATE:
This is my current class:
public partial class TCP_SERVER
{
const int MAX_CLIENTS = 3000;
const int MAX_SOCKET_BUFFER_SIZE = 10;
public AsyncCallback pfnWorkerCallBack;
private Socket m_mainSocket;
private Socket[] m_workerSocket = new Socket[MAX_CLIENTS];
private int m_clientCount = 0;
public GLOBAL_BUFFER;
public void StartServer(int listen_port)
public void OnClientConnect(IAsyncResult asyn)
public void ProcessIncomingData(char[] INCOMING_DATA, int CLIENT_ID)
public void OnDataReceived(IAsyncResult asyn)
}
As you can see GLOBAL_BUFFER is defined 'globally'. If client sends packet_1 that takes 10 seconds to send and at the same time packet_2 that takes 2 secs to send data would get mixed up. I need to collect data for each packet individually.
If at all possible, I would recommend allowing each client thread to have their own connection to the server. Doing so will help the Winsock stack differentiate the messages from each thread and avoid any bleeding of packets between messages. This will effectively allow you to benefit from the stack's ability to decipher which messages (and message segements) are intended to be grouped together before passing them to your application as a complete message.
The message design you describe while very primitive can only work (reliably) if you separate your threads to different connections (or otherwise provide a guarantee that only a single message will be sent from the client at a time). You employee a very primitive message framing technique to your communication which will aide in your effort to determining message boundries but the reason it is failing is because socketData.m_currentSocket.EndReceive(asyn); will only tell you the number of bytes received when the event is raised (not necessarily the total number of bytes in the message). Rather than relying on it to tell you how many bytes have been read, I'd suggest reading the incoming message incrementally from a loop within your async handler reading very small message segments until it discovers your end of message byte sequence. Doing so will tell your event when to quit reading and to pass the data on to something else to process it.
The way I typically approach message framing is to have a before message eye-catcher (some value that will rarely if ever be seen in the messaging), followed by the length of the message (encoded to taste, I personally use binary encoding for it's efficiency), , the message content, and finally a second eye-catcher at the end of your message. The eye-catchers serve as logical queues for message breaks in the protocol and the message length tells your server explicitly how many bytes to wait for. Doing it this way, you are guaranteed to receive the number of bytes necessary (if you don't it is a problem so discard and/or throw exception) and it provides a very explicit boundary between messages that you can code to, which allows intermittent spot checking and validation.
Simply use Dictionary<String,List<Char>> to replace your current GLOBAL_BUFFER,
store different PACKET_ID data into different List.
I strongly recommend you a perfect Socket Framework SuperSocket, you needn't write any socket code, it will significantly improve your development efficiency.

Broken TCP messages

I have a simple TCP server that communicates with some devices via GPRS. It works correctly without any problem for a long time. Nowdays there is a change in the devices (client devices, that send data) and they send lot more data than earlier and TCP message size can be 10 times bigger than earlier. Earlier it was max 1024 bytes/data message, now it can be more than 10 thousand bytes/message.
As I see - as the nature of TCP predicted - there are a lot of messages that are 'broken', so instead of a complete message only a part of that arrives, and later can come the other part etc.
I think my server - that is based on asynchronous pattern - handles this situation in a wrong way and I think the bug is in my RecieveCallBack function. I could not find to correct way to handle this situation. How can I do this?
Here is my RecieveCallBack function:
public void RecieveCallBack(IAsyncResult ar)
{
StateObject state = (StateObject)ar.AsyncState;
try
{
Socket handler = state.WorkSocket;
int read = handler.EndReceive(ar);
if (read > 0)
{
var data = new byte[read];
Array.Copy(state.Buffer, 0, data, 0, read);
}
else
{
if ((handler.Connected == false) || (handler.Available == 0))
{
Close(state);
return;
}
}
}
catch (System.Net.Sockets.SocketException)
{
Close(state);
}
catch (System.Exception exc)
{
Debug.Assert(false, exc.Message);
HandleSocketError(state, exc);
}
}
.net4/c#/vs2010
Thanks
UPDATE:
Clients are connected as they can be connected, so it is up to the GSM network. They can be connected even for days and they send data at every minutes. The protocol of the client devices is different, there are different kind of devices with different kind of protocols. One of them has delimiter and CRC at the end of the message, others does not have.
You need message framing. The protocol must specify how large the messages are - usually either a constant well-known size, a length prefix, or using message delimiters.
The is no such thing as packets in TCP. It is a stream oriented protocol. That means when you read the socket you can get less data than you're expecting. You need to check the read size and if you got a short read then read again for the rest of the data.
For an example in C:
int read_data(int sock, int size, unsigned char *buf) {
int bytes_read = 0, len = 0;
while (bytes_read < size &&
((len = recv(sock, buf + bytes_read,size-bytes_read, 0)) > 0)) {
bytes_read += len;
}
if (len == 0 || len < 0) doerror();
return bytes_read;
}
I am not sure how the rest of the application looks but I think the problem is with the following line :-
Array.Copy(state.Buffer, 0, data, 0, read);
If a packet is fragmented i.e the receive callback is called multiple times for the same connection the state.Buffer will be overwritten with the last received packet, this as you copy data to offset 0 in state.Buffer.
Depending on what your needs are you need to probably need more state in StateObject :) so you can append the data rather than overwrite.
Hope this hint helps.

C# Socket BeginReceive / EndReceive capturing multiple messages

Problem:
When I do something like this:
for (int i = 0; i < 100; i++)
{
SendMessage( sometSocket, i.ToString());
Thread.Sleep(250); // works with this, doesn't work without
}
With or without the sleep the server logs sending of separate messages. However without the sleep the client ends up receiving multiple messages in single OnDataReceived so the client will receive messages like:
0,
1,
2,
34,
5,
678,
9 ....
Server sending Code:
private void SendMessage(Socket socket, string message)
{
logger.Info("SendMessage: Preparing to send message:" + message);
byte[] byteData = Encoding.ASCII.GetBytes(message);
if (socket == null) return;
if (!socket.Connected) return;
logger.Info("SendMessage: Sending message to non " +
"null and connected socket with ip:" + socket.RemoteEndPoint);
// Record this message so unit testing can very this works.
socket.Send(byteData);
}
Client receiving code:
private void OnDataReceived(IAsyncResult asyn)
{
logger.Info("OnDataReceived: Data received.");
try
{
SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
int iRx = theSockId.Socket.EndReceive(asyn);
char[] chars = new char[iRx + 1];
System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
int charLen = d.GetChars(theSockId.DataBuffer, 0, iRx, chars, 0);
System.String szData = new System.String(chars);
logger.Info("OnDataReceived: Received message:" + szData);
InvokeMessageReceived(new SocketMessageEventArgs(szData));
WaitForData(); // .....
Socket Packet:
public class SocketPacket
{
private Socket _socket;
private readonly int _clientNumber;
private byte[] _dataBuffer = new byte[1024]; ....
My hunch is it's something to do with the buffer size or its just the between the OnDataReceived and EndReceive we're getting multiple messages.
Update: It turns out when I put a Thread.Sleep at the start of OnDataReceived it gets every message. Is the only solution to this wrapping my message in a prefix of length and an string to signify the end?
This is expected behaviour. A TCP socket represents a linear stream of bytes, not a sequence of well-delimited “packets”. You must not assume that the data you receive is chunked the same way it was when it was sent.
Notice that this has two consequences:
Two messages may get merged into a single callback call. (You noticed this one.)
A single message may get split up (at any point) into two separate callback calls.
Your code must be written to handle both of these cases, otherwise it has a bug.
There is no need to abandon Tcp because it is stream oriented.
You can fix the problems that you are having by implementing message framing.
See
http://blogs.msdn.com/malarch/archive/2006/06/26/647993.aspx
also:
http://nitoprograms.blogspot.com/2009/04/message-framing.html
TCP sockets don't always send data right away -- in order to minimize network traffic, TCP/IP implementations will often buffer the data for a bit and send it when it sees there's a lull (or when the buffer's full).
If you want to ensure that the messages are processed one by one, you'll need to either set socket.NoDelay = true (which might not help much, since data received may still be bunched up together in the receive buffer), implement some protocol to separate messages in the stream (like prefixing each message with its length, or perhaps using CR/LF to separate them), or use a message-oriented protocol like SCTP (which might not be supported without additional software) or UDP (if you can deal with losing messages).

Windows socket.Send data isn't received until socket.Close

I'm developing a server application that asynchronously accepts TCP connections (BeginAccept/EndAccept) and data (BeginReceive/EndReceive). The protocol requires an ACK to be sent whenever the EOM character is found before it will send the next message. The accept and receive are working but the sending app is not receiving the ACK (sent synchronously).
private void _receiveTransfer(IAsyncResult result)
{
SocketState state = result.AsyncState as SocketState;
int bytesReceived = state.Socket.EndReceive(result);
if (bytesReceived == 0)
{
state.Socket.Close();
return;
}
state.Offset += bytesReceived;
state.Stream.Write(state.Buffer, 0, bytesReceived);
if (state.Buffer[bytesReceived - 1] == 13)
{
// process message
Messages.IMessage message = null;
try
{
var value = state.Stream.ToArray();
// do some work
var completed = true;
if (completed)
{
// send positive ACK
var ackMessage = string.Format(ack, message.TimeStamp.ToString("yyyyMMddhhmm"), message.MessageType, message.Id, "AA", message.Id);
var buffer = ASCIIEncoding.ASCII.GetBytes(ackMessage);
int bytesSent = state.Socket.Send(buffer, 0, buffer.Length, SocketFlags.None);
}
else
{
// send rejected ACK
var ackMessage = string.Format(ack, message.TimeStamp.ToString("yyyyMMddhhmm"), message.MessageType, message.Id, "AR", message.Id);
state.Socket.Send(ASCIIEncoding.ASCII.GetBytes(ackMessage));
}
}
catch (Exception e)
{
// log exception
// send error ACK
if (message != null)
{
var ackMessage = string.Format(ack, DateTime.Now.ToString("yyyyMMddhhmm"), message.MessageType, message.Id, "AE", message.Id);
state.Socket.Send(ASCIIEncoding.ASCII.GetBytes(ackMessage));
}
}
}
state.Socket.BeginReceive(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, new AsyncCallback(_receiveTransfer), state);
}
The state.Socket.Send returns the correct number of bytes but the data isn't received until the socket is disposed.
Suggestions are appreciated.
you shouldn't do anything synchronous from async completion routines. Under load you can end up hijacking all IO completion threads from the thread pool and severly hurt performance, up to and including complete IO deadlock. So don't send ACKs synchronously from async callback.
protocols and formats that use preambles are easier to manage that those that use terminators. Ie. write the length of the message in the fixed size message header as opposed to detecting a terminator \0x13. Of course, this applies if the protocol is under your control to start with.
As for your question, you didn't specify if the same code as you posted is also on the client side too.
How long are you giving it? The network stack can buffer, and that could delay transmition. From MSDN:
To increase network efficiency, the
underlying system may delay
transmission until a significant
amount of outgoing data is collected.
A successful completion of the Send
method means that the underlying
system has had room to buffer your
data for a network send.
You might want to try flushing using the IOControl method.
edit
Actually, the IOControl flush will kill the buffer. You may want to check out the Two Generals Problem to see if your protocol will have some inherent problems.
try setting TCP_NODELAY socket option
Have you set the NoDelay property on the socket to true? When set to false (the default), data is buffered for up to 200 milliseconds before it's sent. The reason is to reduce network traffic by limiting the number of packets that are sent. Setting NoDelay to true will force the data to be sent sooner.

Categories

Resources