借助C TCP套接字,可以“发送”返回零?

发布于 2024-09-06 08:46:41 字数 92 浏览 7 评论 0原文

使用 TCP 套接字时,C send 函数是否有可能返回零?手册页只是说它将返回发送的字节数,但我不确定当它无法发送任何数据时它是否会返回-1。

Is it ever possible for the C send function to return zero when using TCP sockets? The man page just says that it will return the number of bytes sent, but I am not sure if it will just return -1 when it can't send any data.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

笑叹一世浮沉 2024-09-13 08:46:41

我很确定,虽然记忆深处在时间的迷雾中,但我以前见过它在另一端跟不上的大量数据传输的情况下返回零。

根据记忆,在这种情况下,远程 TCP 堆栈缓冲区已填满,堆栈已通知本地端要延迟,直到清除了一些空间并且本地缓冲区也已填满。

此时,从技术上讲,这并不是一个错误(因此没有返回 -1),但本地堆栈无法接受任何数据。

我不完全确定现在的情况是这样,因为当前的 Posix 标准似乎表明在这种情况下它将简单地阻塞(或者如果设置为非阻塞则失败)。

然而,我怀疑这是一个有争议的问题。您确实有可能返回少于您请求发送的字节,因此您应该有适当的代码来处理这个问题。

而且,由于处理“比您请求的少一”的逻辑与处理“零字节”的逻辑几乎相同,因此您也可以假设它可以返回零。

I'm pretty certain, though the memory is deep in the mists of time, that I've seen it return zero before, in the situation of massive data transfers where the other end was not keeping up.

From memory, in that case, the remote TCP stack buffers had filled up, the stack had notified the local end that it was to delay until some space was cleared out and the local buffers had filled up as well.

At that point, it's not technically an error (hence no -1 returned) but no data could be accepted by the local stack.

I'm not entirely certain that's the case now since the current Posix standard seems to indicate it will simply block in that case (or fail if it's set up for non-blocking).

However, I suspect it's a moot point. You do have the possibility that it will return less than the bytes you requested to send and you therefore should have code in place to handle that.

And, since it will be pretty much the same logic handling 'one less than what you requested' as handling 'zero bytes', you may as well assume it can return zero.

倾城泪 2024-09-13 08:46:41

好吧,总是存在这样的情况:您传入零作为要发送的字节数...在这种情况下,“返回发送的字节数”将表明它应该返回零字节。

无论如何,最好正确处理返回零的情况;它不会造成伤害,而且可能会有所帮助。

Well, there is always the case where you passed in zero as the number of bytes to send... in that case, "returning the number of bytes sent" would indicate that it should return zero bytes.

Probably best to handle the returns-zero case properly anyway; it can't hurt, and it might help.

醉酒的小男人 2024-09-13 08:46:41

这个问题的答案很可能取决于实现,因此根据操作系统的不同而有所不同。

当您请求传输 0 字节时,预期会出现 0 的一种情况。

The answer to this may well be implementation dependent and therefore vary based on the operating system.

One circumstance where 0 would be expected, when you request a transmission of 0 bytes.

青瓷清茶倾城歌 2024-09-13 08:46:41

BSD man 页面指出:

如果套接字上没有可用的消息空间来保存要传输的消息,则 send() 通常会阻塞,除非套接字已置于非阻塞 I/O 模式。

Posix 规范更进一步指出,在阻塞模式下,除非发生中断,否则所有数据都会被传输。

在这两种情况下,除非提供的计数为零,否则无法返回零。

The BSD man page states:

If no messages space is available at the socket to hold the message to be transmitted, then send() normally blocks, unless the socket has been placed in non-blocking I/O mode.

The Posix specification goes further and states that in blocking mode all data is transferred, unless an interrupt occurs.

In both cases zero cannot be returned unless the count supplied was zero.

[浮城] 2024-09-13 08:46:41

我现在确实观察到 AF_UNIX 类型套接字上的 send(2) 返回零。

是的,这是由于 size 字段的值为零。

所以,JFYI。

I do observe a zero return from the send(2) on an AF_UNIX type socket right now.

Yepp, it was due to the size field of zero value.

So, JFYI.

注定孤独终老 2024-09-13 08:46:41

send 当您 send(socket, buf, 0, 0) 时返回 0

我想提供简单的代码供其他人测试。

服务器:

在一个终端中:

nc -l localhost 10086

客户端:

在另一个终端中:

#include <cstdio>
#include <cstdlib>

#include <unistd.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include <netdb.h>
#include <arpa/inet.h>

int create_socket()
{
    addrinfo  hints = {};
    addrinfo* servinfo;

    int sockfd = -1;
    int rv;

    hints.ai_family   = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags    = 0;

    if ((rv = getaddrinfo("localhost", "10086", &hints, &servinfo)))
    {
        printf("getaddrinfo failed: %s\n", gai_strerror(rv));
        exit(1);
    }

    for(auto p = servinfo; p; p = p->ai_next)
    {
        if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
        {
            perror("socket");
            continue;
        }

        else
        {
            if(connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)
            {
                close(sockfd);
                perror("connect");
                continue;
            }
            else
                puts("client: connected");
        }

        break;
    }

    freeaddrinfo(servinfo);
    return sockfd;
}

void client()
{

    int socket = create_socket();

    if(socket == -1)
    {
        puts("no good");
        exit(1);
    }
    char buf[100] = {0};

    while(1){
        int ret = send(socket, buf, 0, 0);
        if (ret == 0){
            printf(".");
        }else{
            printf("xxxxxxx\n");
        }
    }
}


int main()
{
    setvbuf(stdout, NULL, _IONBF, 0);
    client();
    return 0;
}
g++ -g -Wall -o send_zero_bytes send_zero_bytes.cpp
./send_zero_bytes 

send returns 0 when you send(socket, buf, 0, 0)

I'd like to provide simple code for others to test.

Server:

In one terminal:

nc -l localhost 10086

Client:

In another terminal:

#include <cstdio>
#include <cstdlib>

#include <unistd.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include <netdb.h>
#include <arpa/inet.h>

int create_socket()
{
    addrinfo  hints = {};
    addrinfo* servinfo;

    int sockfd = -1;
    int rv;

    hints.ai_family   = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags    = 0;

    if ((rv = getaddrinfo("localhost", "10086", &hints, &servinfo)))
    {
        printf("getaddrinfo failed: %s\n", gai_strerror(rv));
        exit(1);
    }

    for(auto p = servinfo; p; p = p->ai_next)
    {
        if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
        {
            perror("socket");
            continue;
        }

        else
        {
            if(connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)
            {
                close(sockfd);
                perror("connect");
                continue;
            }
            else
                puts("client: connected");
        }

        break;
    }

    freeaddrinfo(servinfo);
    return sockfd;
}

void client()
{

    int socket = create_socket();

    if(socket == -1)
    {
        puts("no good");
        exit(1);
    }
    char buf[100] = {0};

    while(1){
        int ret = send(socket, buf, 0, 0);
        if (ret == 0){
            printf(".");
        }else{
            printf("xxxxxxx\n");
        }
    }
}


int main()
{
    setvbuf(stdout, NULL, _IONBF, 0);
    client();
    return 0;
}
g++ -g -Wall -o send_zero_bytes send_zero_bytes.cpp
./send_zero_bytes 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文