Search code examples
c#socketstcptcpclient

Multiple Client Sockets from one instance of a program connecting different devices- working really slow


I have built application that connects with help of TCP Sockets to 4 devices. For that i created an TCP class with asynchronous methods to send and receive data.

public delegate void dataRec(string recStr);
public event dataRec dataReceiveEvent;
public Socket socket;
public void Connect(string IpAdress, int portNum)
{
 socket  = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
 IPEndPoint epServer = new IPEndPoint(IPAddress.Parse(IpAdress), portNum);
 socket.Blocking = false;
 AsyncCallback onconnect = new AsyncCallback(OnConnect);
 m_sock.BeginConnect(epServer, onconnect, socket);
}
            

public void SetupRecieveCallback(Socket sock)
    {
        try
        {
            AsyncCallback recieveData = new AsyncCallback(OnRecievedData);
            sock.BeginReceive(m_byBuff, 0, m_byBuff.Length, SocketFlags.None, recieveData, sock);
        }
        catch (Exception ex)
        {
            //nevermind
        }
       
    }
 public void OnRecievedData(IAsyncResult ar)
    {
        // Socket was the passed in object
        Socket sock = (Socket)ar.AsyncState;
        try
        {
            int nBytesRec = sock.EndReceive(ar);
            if (nBytesRec > 0)
            {
                string sRecieved = Encoding.ASCII.GetString(m_byBuff, 0, nBytesRec);
                OnAddMessage(sRecieved);
                SetupRecieveCallback(sock);
            }
            else
            {
                sock.Shutdown(SocketShutdown.Both);
                sock.Close();
            }
        }
        catch (Exception ex)
        {
            //nevermind
        }
    
    }
  public void OnAddMessage(string sMessage)
    {
        if (mainProgram.InvokeRequired)
        {
            {
                scanEventCallback d = new scanEventCallback(OnAddMessage);
                mainProgram.BeginInvoke(d, sMessage);
            }
        }
        else
        {
            dataReceiveEvent(sMessage);
        }
    }

I have 4 devices with 4 different IP's and Port's that i send data, and from which i receive data.

So i created 4 different instances of a class mentioned. When i receive data i call callback functions to do their job with the data i received (OnAddMessage event).

The connection with devices is really good, latency is like: 1-2ms~ (its in internal network).

Functions i call by callbacks are preety fast, each function is not more than 100ms.

The problem is it is working really slow, and its not caused by callback functions. For each data i send to device, i receive one message from it. When i start sending them, and stop after like 1 minute of working, the program keep receiving data for like 4-5 sec, even when i turn off devices- its like some kind of lag, that i receive data, that should be delivered a lot earlier. It looks like something is working really slow.

Im getting like 1 message per second from each device, so it shouldnt be a big deal.

Any ideas what else i should do or set, or what actually could slow me down ?


Solution

  • You haven't posted all the relevant code, but here are some things to pay attention to:

    • With a network sniffer, like Wireshark or tcpdump, you can see what is actually going on.
    • Latency it not the only relevant factor for "connection speed". Look also at throughput, packet loss, re-transmissions, etc..
    • Try to send and receive in large chunks. Sending and receive only single bytes is slow because it has a lot of overhead.
    • The receiver should read data faster than the sender can send it, or else internal buffers (OS, network) will fill up.
    • Try to avoid a "chatty" protocol, basically synchronous request/reply, if possible.
    • If you have a chatty protocol, you can get better performance by disabling the Nagle algorithm. The option to disable this algorithm is often called "TCP no delay" or similar.
    • Don't close/reopen the connection for each message. TCP connection setup and teardown has quite some overhead.
    • If you have long standing open TCP connections, close the connection when the connection is idle for some time, for example several minutes.