2014-09-18 47 views
0

在HFT交易应用程序中,我需要从udp多播套接字接收数据。唯一的要求是延迟 - 这非常重要,我可以“花费”一个CPU内核。无论旋转或其他什么都可以。这是我目前在Windows中:以最低的延迟从linux的多播套接字接收数据

void Receiver::ThreadMethod() { 
    //UINT32 seq; 
    sockaddr_in Sender; 
    int SenderAddrSize = sizeof(Sender); 

    while (stayConnected) { 
     int res=recvfrom(socketId,buf,sizeof(char) * RECEIVE_BUFFER_SIZE,0, (SOCKADDR *)& Sender, &SenderAddrSize); 
     if (res == SOCKET_ERROR) { 
      printf("recvfrom failed, WSAGetLastError: %d\n", WSAGetLastError()); 
      continue; 
     } 
     //seq = *(UINT32*)buf; 
     //printf("%12s:seq=%6d:len=%4d\n", inet_ntoa(Sender.sin_addr), seq, res); 
     unsigned char* buf2 = reinterpret_cast<unsigned char*>(buf); 
     feed->ProcessMessage(res, buf2); 
    } 
} 

recvfrom块,所以这将是有可能很慢(或我错了?)。我应该重写这个Linux版本,并实现最佳的延迟。我需要每个线程只处理一个套接字,所以我认为我不应该使用epoll,因为它设计了更多处理多个套接字。我应该使用什么?

UPD我找到了类似的问题Low-latency read of UDP port

+1

目前尚不清楚为什么你认为阻塞recvfrom()调用会很慢。确实如果没有收到数据包,它将不会长时间返回,但是如果/当收到数据包时它应该立即返回。您担心的是上下文切换开销吗? – 2014-09-18 19:50:46

+0

顺便说一句,如果你想保证低延迟,你可以看看Xenomai的Linux实时扩展,因为这是他们提供的。 – 2014-09-18 19:51:48

+0

@JeremyFriesner阻止永远是昂贵的,这就是为什么人们“旋转” – javapowered 2014-09-18 20:00:11

回答

0

在UNIX中,你应该使用fcntl设置您的插座非阻塞:

fcntl(socket, F_SETFL, O_NONBLOCK); 

此外,如果客户需要处理多个插座(例如聚合多个提要),您应该使用一个select调用来一次处理多个文件描述符,并查看哪个套接字有可用的数据(如果有的话)(除此之外,这将避免在所有套接字中循环)

至于延迟,其他因素(如NIC类型和配置),内核设置(可能有一个绕过内核的NIC)将对延迟(待测量)产生相当大的影响。

+0

据我所知,在低延迟情况下最好使用“一个线程 - 一个插座”。还要注意我在两个套接字上都收到了相同的数据。使用两个线程可以并行接收两个数据包,这应该会稍稍改善延迟。 – javapowered 2014-09-18 20:02:14

+0

网卡和其他一切都是辉煌的配置和在这个星球上最快,只有软件尚未写入。 – javapowered 2014-09-18 20:03:55

+0

@javapowered不,它不是“一个线程一个套接字”,大多数处理程序在一个或两个CPU上旋转选择,但这一切都取决于您的可用硬件。 (无论如何多个步骤可以并发访问NIC +上下文切换成本来运行它们)。跳这有助于。 – quantdev 2014-09-18 20:14:26