socket编程中无效参数errno 22(recv()函数)C语言

问题描述 投票:0回答:1

我正在编写一个函数来从套接字接收数据,将其存储在缓冲区中返回我读取的字节数和其他一些检查,我几天无法调试它。

单元测试:


#define BUFFSIZE 2

void
test_handle_read_socket() {
    /* Arrangement */
    struct conn sender;
    int sockfd[2];

    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) == -1) {
        perror("Failed creating pair sockets.");
        return;
    }

    // int flags = fcntl(sockfd[0], F_GETFL, 0);
    // fcntl(sockfd[0], F_SETFL, flags | O_NONBLOCK);

    // write "123" to the pipe.
    sender.pfd.fd = sockfd[0];
    send(sockfd[1], "123", 3, 0);

    eqint(2, handle_read_socket(&sender));
    eqnstr("12", sender.client_buff, 2);
    eqint(1, handle_read_socket(&sender)); // Tag: The problem, return -1 instead of 1
    eqnstr("3", sender.client_buff, 1);

    /* Teardown */
    close(sockfd[1]);
    close(sockfd[0]);
}

实施:

struct conn {
    struct pollfd pfd;
    struct sockaddr_in client_addr;
    char client_buff[BUFFSIZE];
    char server_buff[BUFFSIZE];
};



int
handle_read_socket(struct conn *client) {
    int total_read = 0;
    int readsize = 0;

    while (1) {
        readsize = recv(client->pfd.fd, client->client_buff + total_read,
                        BUFFSIZE - total_read, 0);

        if (readsize > 0) {
            total_read += readsize;

            if (total_read == BUFFSIZE) {
                // Buffer is full.
                break;
            }
        } else if (readsize == 0) {
            // client closed connection.
            if (errno == EOF) {
                return -1;
            }
            else {
                // An error happened.
                LOG_ERROR("Something unpredictable happened.");
                return -1;
            }
        } else {
            // Client has no data(non blocking).
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                break;
            }
            // An error happened.
            LOG_ERROR("Could not read from client and Error happened.")
            return -1;
        }
    }
    return total_read;
}

当它第一次循环时(单元测试中的标签)recv()返回1,这是正确的,但缓冲区中的字符“3”,但第二次recv()返回-1并将errno设置为22,这是我的问题。 (将文件描述符设置为非阻塞模式不起作用。)

sockets recv errno
1个回答
0
投票

我相信你的问题就在这里:

    } else if (readsize == 0) {
        // client closed connection.
        if (errno == EOF) {
            return -1;
        }

特别是,第二次调用

handle_read_socket()
时,会调用
recv()
recv()
会返回
1
;然后
handle_read_socket()
将再次调用
recv()
(因为
total_read < BUFFSIZE
),这次
recv()
将返回
0
(因为服务器在发送所有三个字节后已关闭TCP连接),这会导致上面的代码无济于事地返回 -1,即使它已经读取了一个字节的有效数据。

作为修复,您可以将代码更改为类似这样的内容:

    } else if (readsize == 0) {
        // client closed connection.
        if (errno == EOF) {
            return (total_read > 0) ? total_read : -1;
        }

...这样,读取一些有效数据的事实将如您所期望的那样反映在返回值中。 如果第三次调用

handle_read_socket()
,则
recv()
将在第一次尝试时返回
0
,此时将返回
-1
以指示出现问题。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.