3

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?

LarsTech
  • 80,625
  • 14
  • 153
  • 225
FuzzyLogic
  • 31
  • 3
  • 1
    Putting the thread in sleep mode when the data is not there yet is actually a good thing from the resource management perspective. I don't quite get your point of fully utilizing the CPU capacity. If the data is not there yet, what do you expect CPU running? Just an empty loop keep polling the data? – Harvey Kwok Jan 15 '12 at 20:00
  • Yes I would like to make a while loop that continues to poll for data. Basically so that a thread does not have to take any time to wake up. – FuzzyLogic Jan 15 '12 at 20:15
  • 1
    That accomplishes the *exact opposite*, the thread will burn up its quantum and not get scheduled for a while. It significantly increases the latency. – Hans Passant Jan 15 '12 at 20:39
  • You want to be ultra-fast but you're using TCP? what happens when you drop a packet? TCP will block all incoming data until successful retransmission. –  Jun 23 '12 at 21:23

3 Answers3

1

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
        // ...
    }
}
Marlon
  • 19,924
  • 12
  • 70
  • 101
  • With BeginReceive() the call to ReceiveCallBack() is made through the threadpool correct? I need to control the number of threads that are running, and the latency of a threadpool is too unreliable for this application. – FuzzyLogic Jan 15 '12 at 20:19
1

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...
Tudor
  • 61,523
  • 12
  • 102
  • 142
0

Perhaps side step the whole problem of sending data over a network by checking out networkComms.net and in particular the short example demonstrating the most basic functionality here, hopefully not overly complex! Most of the problems you might come across will already have been solved and it might save you some time.

MarcF
  • 3,169
  • 2
  • 30
  • 57