【问题标题】:Sending large data via socket通过套接字发送大数据
【发布时间】:2012-10-16 10:25:53
【问题描述】:

我正在通过套接字发送大数据(嗯……1Mb),但我不知道为什么发送操作会阻塞程序并且永远不会结束。小型发送完美运行,我找不到问题出在哪里。有人可以帮帮我吗?

提前感谢您提供的任何帮助。

int liResult = 1;
int liConnection = 0;
int liSenderOption = 1;
struct addrinfo laiSenderAddrInfo;
struct addrinfo *laiResultSenderAddrInfo;

memset(&laiSenderAddrInfo,0,sizeof(laiSenderAddrInfo));
laiSenderAddrInfo.ai_socktype = SOCK_STREAM;
laiSenderAddrInfo.ai_flags = AI_PASSIVE;

liResult = getaddrinfo(_sIp.c_str(), _sPort.c_str(), &laiSenderAddrInfo, &laiResultSenderAddrInfo);

if (liResult > -1)
{
    liConnection = socket(laiResultSenderAddrInfo->ai_family, SOCK_STREAM, laiResultSenderAddrInfo->ai_protocol);
    liResult = liConnection;

    if (liConnection > -1)
    {
        setsockopt(liConnection, SOL_SOCKET, SO_REUSEADDR, &liSenderOption, sizeof(liSenderOption));
        liResult = connect(liConnection, laiResultSenderAddrInfo->ai_addr, laiResultSenderAddrInfo->ai_addrlen);
    }
}

size_t lBufferSize = psText->length();
long lBytesSent = 1;
unsigned long lSummedBytesSent = 0;

while (lSummedBytesSent < lBufferSize and lBytesSent > 0)
{
    lBytesSent = send(liConnection, psText->c_str() + lSummedBytesSent, lBufferSize - lSummedBytesSent, MSG_NOSIGNAL);

    if (lBytesSent > 0)
    {
        lSummedBytesSent += lBytesSent;
    }
}

【问题讨论】:

    标签: c++ linux sockets networking tcp


    【解决方案1】:

    检查缓冲区大小,你可以按照这个答案来做

    How to find the socket buffer size of linux

    在我的例子中,值是

    Minimum = 4096 bytes ~ 4KB
    Default = 16384 bytes ~ 16 KB
    Maximum = 4022272 bytes ~ 3.835 MB
    

    您可以调整/etc/sysctl.conf 中的值net.core.rmem_maxnet.core.wmem_max 以增加套接字缓冲区大小并使用sysctl -p 重新加载。

    来源:http://www.runningunix.com/2008/02/increasing-socket-buffer-size-in-linux/

    【讨论】:

      【解决方案2】:

      send() 调用会阻塞,直到所有数据都已发送或缓冲。如果套接字另一端的程序没有读取,因此没有数据流,那么你端的写缓冲区将填满,send() 将阻塞。当您尝试发送较少量的数据时,它可能适合缓冲区。

      另见this answer.

      【讨论】:

        【解决方案3】:

        对于 TCP,内核有一个固定大小的缓冲区,用于存储未发送的数据。此缓冲区的大小是 TCP 会话的当前窗口大小。一旦此缓冲区已满,任何新发送都将失败。这是一种 TCP 流控制机制,可防止您尝试发送数据的速度快于接收方消耗数据的速度,同时为丢失的数据提供自动重新发送。默认窗口可以小至 64K,但对于高延迟高带宽网络可以增大。

        您可能需要做的是将数据分解为更小的发送块,然后确保在发送缓冲区已满时有一个流出机制。

        【讨论】:

        • OP 没有失败;他正在阻塞:很明显他没有处于非阻塞模式,我希望当你说“失败”(EAGAIN / EWOULDBLOCK)时你指的是什么。默认的 TCP 窗口可以比 64k 小很多:例如在 Windows 上尝试 8k;除非您在分别调用accept()connect() 之前采取特殊措施,否则它不能超过64k-1。将数据分解成更小的发送块对这个问题的影响为零。投反对票。
        猜你喜欢
        • 2012-10-13
        • 2020-12-03
        • 1970-01-01
        • 2011-03-12
        • 1970-01-01
        • 2016-04-06
        • 2011-06-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多