Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent Thread From Sleeping When Calling Socket.Receive

I'm working on a low latency financial application that receives tcp data over sockets.
This is how I'm making a socket connection and receiving bytes:

public class IncomingData
{
  Socket _Socket;
  byte[] buffer = new byte[4096];

  public static void Connect(IPEndPoint endPoint)
  {
    _Socket = new Socket(
                  AddressFamily.InterNetwork,
                  SocketType.Stream, 
                  ProtocolType.Tcp);

    _Socket.Connect(endPoint);
  }

  public static void ReadSocket(int ReadQty)
  {
    _Socket.Receive(buffer, 0, ReadQty, SocketFlags.None); 
  }
}

I heard that when you call Receive() on a Stream socket, that the calling thread is put to sleep, and it is woken up when data is received. I would like the thread to be running at full speed (using CPU capacity).

Is there a way I can do this using a Stream socket? If the only way is with a Raw socket, could you provide an example?

like image 710
FuzzyLogic Avatar asked Sep 11 '26 06:09

FuzzyLogic


2 Answers

If I understand you correctly, you want Receive to not block?

Take a look at the BeginX/EndX methods of the socket class. These methods perform asynchronously (not blocking on the current thread). They accept a callback method as one of their parameters and that method will be called when the operation completes (in this case, data would be received). It is essentially the same as events.

public class IncomingData
{
    Socket _Socket;
    byte[] buffer = new byte[4096];

    public static void Connect(IPEndPoint endPoint)
    {
        _Socket = new Socket(
                      AddressFamily.InterNetwork,
                      SocketType.Stream, 
                      ProtocolType.Tcp);        

        _Socket.Connect(endPoint);

    }

    public static void ReadSocket(int ReadQty)
    {
         // Wait for some data to be received. When data is received,
         // ReceiveCallback will be called.
         _Socket.BeginReceive(buffer, 0, ReadQty, SocketFlags.None, ReceiveCallback, null);
    }

    private static void ReceiveCallback(IAsyncResult asyncResult)
    {
        int bytesTransferred = _Socket.EndReceive(asyncResult);

        // ...
        // process the data
        // ...
    }
}
like image 142
Marlon Avatar answered Sep 13 '26 20:09

Marlon


You can use Socket.Poll to determine if the socket has data and keep spinning otherwise:

// will spin here until poll returns true
while(!socket.Poll(0, SelectMode.SelectRead));
socket.Receive...
like image 33
Tudor Avatar answered Sep 13 '26 21:09

Tudor