C ++网络套接字,SCTP和数据包大小

时间:2013-08-26 10:15:53

标签: c++ sockets networking packet sctp

我目前正在使用面向连接的SCTP开发服务器来为少数客户端提供服务。在完成第一个原型实现后,我现在正在分析应用程序以进行优化。事实证明,CPU时间的两个主要消费者之一是网络部分。

关于我实施的应用程序级协议的效率,有两个问题:

1)数据包大小

目前,我使用的最大数据包大小为64字节。您可以找到许多帖子讨论数据包大小太大,但它们是否太小?由于SCTP允许我一次读取一个数据包 - 类似于UPD - 同时保证按顺序传送 - 类似于TCP - 这显着简化了实现。但是,如果我理解正确的话,每次发送数据包时都会花费一个系统调用。系统调用的数量是否会对性能产生重大影响?通过以更大的数据包(即1024 - 8192字节)串行发送消息,我是否能够节省大量的CPU周期?

2)读取和写入缓冲区

我目前正在使用memcpy将数据移入和移出应用程序级网络缓冲区。我发现很多关于什么是更高效,memcpy或正常分配的相互矛盾的帖子。我想知道在这种情况下,一种方法是否会明显快于另一种方法:

选项1

void Network::ReceivePacket(char* packet)
{
    uint8_t param1;
    uint16_t param2
    uint32_t param3;

    memcpy(&param1, packet, 1);
    memcpy(&param2, packet+1, 2);
    memcpy(&param3, packet+3, 4);

    // Handle the packet here
}

void Network::SendPacket(uint8_t param1, uint16_t param2, uint32_t param3)
{
    char packet[7]

    memcpy(&packet, &param1, 1);
    memcpy(&packet+1, &param2, 2);
    memcpy(&packet+3, &param3, 4);

    // Send the packet here
}

选项2

void Network::ReceivePacket(char* packet)
{
    uint8_t param1;
    uint16_t param2
    uint32_t param3;

    param1 = *((uint8_t*)packet);
    param2 = *((uint16_t*)packet+1);
    param3 = *((uint32_t*)packet+3);

    // Handle the packet here
}

void Network::SendPacket(uint8_t param1, uint16_t param2, uint32_t param3)
{
    char packet[7]

    *((uint8_t*)packet) = param1;
    *((uint16_t*)packet+1) = param2;
    *((uint32_t*)packet+3) = param3;

    // Send the packet here
}

第一个似乎对我来说更清洁,但我发现很多帖子表明第二个可能要快得多。

当然欢迎任何形式的反馈。

3 个答案:

答案 0 :(得分:0)

据我所知,编译器特别优化了memcpy调用,所以你应该使用它。

关于你的第一个问题:

  • 摘要:尽可能减小数据包的大小,避免出现CPU性能下降的可能性。

系统调用syscall是您的操作系统回复或处理您的请求以及每次在内核中执行请求时,这是一项适度的工作。 说实话,我不熟悉SCTP概念,事实上,自从我上次处理一些东西并通过TCP创建服务器以来,我还没有处理套接字编程。我记得相关物理层元素的MTU是1500,我还记得将我的数据包大小实现为1450-1460,因为我试图在1500上限下方获得最大数据包大小。

所以我说的是如果我是你,我会希望我的操作系统不那么活跃,因此我不会遇到任何CPU性能问题。

答案 1 :(得分:0)

如果您希望最大限度地减少系统调用次数,并且确实发现自己一次发送和接收多条消息,则可能需要查看(仅限Linux)sendmmsg()和{{ 3}}

要使用这些,您可能需要在内部对消息进行排队,这可能会增加其他情况下不会存在的延迟。

答案 2 :(得分:0)

我个人不会超过1024的缓冲区大小。我在使用超过1500的数据包时遇到了一些运行时问题,但1024当然是4到5的功率使它很好用。 这是可能的,但我不建议。我会使用recvmsg()创建一个单独的线程来接收数据包,这样你就可以使用多个流。我发现这个工作很精彩。 SCTP的要点是多个流,所以我会充分利用它。一旦收到所有内容,您就必须确保数据以正确的顺序放回(这需要做一些工作)。