简体   繁体   English

C 套接字 send() 在 Main 函数返回之前不会发送所有数据

[英]C socket send() dose not send all data before Main function returned

Here is the succinct code:这是简洁的代码:

int main(){
    /* here ellipsis socket connect malloc etc. */

    send(socket,buffer, 1024*1024*1024,0);
    return 1;
}

Question: If send() is blocked, no matter how large the buffer is, I think it will send all data before the main function returned.问题:如果send()被阻塞,不管缓冲区有多大,我认为它会在main函数返回之前发送所有数据。 But actually, if the data large enough, the other socket end only receive a part of data which the send() function send.但实际上,如果数据足够大,另一个socket端只接收send()函数发送的一部分数据。 However, if I add this code before 'return 1;'但是,如果我在 'return 1;' 之前添加此代码

while(1){}

the other socket end receive intact data.另一个套接字端接收完整的数据。

Does the send() is non_blocked? send()是非阻塞的吗? or something wrong with send() function?还是send()函数有问题?

thanks advance.提前感谢。

When blocking socket is used, send() function blocks until last data is delivered to queue of local TCP-stack.当使用阻塞套接字时, send()函数会阻塞,直到最后一个数据被传送到本地 TCP 堆栈的队列。

So send() may return when part of the data is still queued in local TCP-stack.因此,当部分数据仍在本地 TCP 堆栈中排队时, send()可能会返回。 Because your process exits right after send() call, there can be undelivered data in local TCP stack during exit.由于您的进程在send()调用后send()退出,因此退出期间本地 TCP 堆栈中可能存在未传递的数据。

TCP stack may continue the data transfer after exit, if linger is enabled.如果启用了延迟,TCP 堆栈可以在退出后继续数据传输。 Or TCP stack may reset the connection without any attempt to transfer undelivered data to the peer, if linger is disabled.或者 TCP 堆栈可能会在不尝试将未传递的数据传输到对等方的情况下重置连接,如果 linger 被禁用。

If you close the TCP connection gracefully when linger is enabled, then TCP-stack should (try to) deliver queued data to the peer.如果在启用 linger 时正常关闭 TCP 连接,则 TCP 堆栈应该(尝试)将排队的数据传递给对等方。

Close the connection gracefully by adding close() call.通过添加close()调用优雅地关闭连接。 And make sure that SO_LINGER is enabled with reasonable timeout:并确保在合理的超时时间内启用 SO_LINGER:

send(socket,buffer, 1024*1024*1024,0);

const struct linger linger_val = { 1, 600 };
setsockopt(socket, SOL_SOCKET, SO_LINGER, &linger_val, sizeof(linger_val));

close(socket);
return 1;

Usually there is no need to change SO_LINGER.通常不需要更改 SO_LINGER。 More information about SO_LINGER in man page of socket(7) : socket(7) 手册页中有关 SO_LINGER 的更多信息:

SO_LINGER
              When enabled, a close(2) or shutdown(2) will not return until
              all queued messages for the socket have been successfully sent
              or the linger timeout has been reached.  Otherwise, the call
              returns immediately and the closing is done in the background.
              When the socket is closed as part of exit(2), it always
              lingers in the background.

Whit 0 as flag, send() is like write() function: Whit 0 作为标志, send()就像write()函数:

and for write() :对于write()

The number of bytes written may be less than count if, for example, there is insufficient space on the underlying physical medium, or the RLIMIT_FSIZE resource limit is encountered (see setrlimit(2)), or the call was interrupted by a signal handler after having written less than count bytes.写入的字节数可能小于 count,例如,底层物理介质上的空间不足,或者遇到 RLIMIT_FSIZE 资源限制(请参阅 setrlimit(2)),或者调用在之后被信号处理程序中断写入少于 count 个字节。 (See also pipe(7).). (另见管道(7)。)。

Check also this answer:也检查这个答案:

Blocking sockets: when, exactly, does "send()" return? 阻塞套接字:确切地说,“send()”何时返回?

Hope this help希望这有帮助

send() is blocking call, but it is blocked till all the data is pushed to sendbuffer . send()正在阻塞调用,但它会被阻塞,直到所有数据都被推送到sendbuffer You can modify the program to exit when all the data is send from the socket.您可以修改程序以在所有数据从套接字发送时退出。 This is possible by reducing the sendbuffer size.这可以通过减少sendbuffer大小来实现。 you can use setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)send_buffer, send_buffer_sizeof);你可以使用setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)send_buffer, send_buffer_sizeof);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM