python - tcp 套接字,select 告诉可写,但 write() 会阻塞

标签 python c sockets select tcp

我编写了一个小的 tcp 套接字服务器程序,使用 select() 来检查客户端套接字是否可写。如果客户端可写,我将向其写入数据。

客户端是用Python编写的,仅用于测试,它连接到服务器,并且从不从连接中读取。

结果是,服务器 write() 最终阻塞。

服务器(C):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <sys/select.h>

int main(int argc, char **argv){
    int serv_sock;
    struct sockaddr_in addr;
    const char *ip = "0.0.0.0";
    int opt = 1;
    int port = 7000;
    if(argc > 2){
        port = atoi(argv[1]);
    }

    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons((short)port);
    inet_pton(AF_INET, ip, &addr.sin_addr);

    serv_sock = socket(AF_INET, SOCK_STREAM, 0);
    setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    bind(serv_sock, (struct sockaddr *)&addr, sizeof(addr));
    listen(serv_sock, 1024);

    printf("server listen on port: %d\n", port);

    int sock = accept(serv_sock, NULL, NULL);
    printf("accepted\n");

    while(1){
        fd_set w_set;
        FD_ZERO(&w_set);
        int maxfd = sock;
        FD_SET(sock, &w_set);
        int ret = select(maxfd + 1, NULL, &w_set, NULL, NULL);
        if(ret < 0){
            if(errno == EINTR){
                continue;
            }else{
                printf("select error! %s\n", strerror(errno));
                exit(0);
            }
        }
        char buf[128 * 1024];
        if(FD_ISSET(sock, &w_set)){
            printf("write begin\n");
            int n = write(sock, buf, sizeof(buf));
            printf("write %d\n", n);
        }
    }

    return 0;
}

客户端(Python):

import socket
s = socket.socket()
s.connect(('127.0.0.1', 7000))

输出:

$ gcc a.c; ./a.out 
server listen on port: 7000
accepted
write begin
write 131072
write begin
write 131072
write begin
write 131072
write begin
write 131072
write begin
write 131072
write begin

我的问题是:即使 select 告诉可写,为什么 write() 操作也会阻塞? select() 的手册说:

A file descriptor is considered ready if it is possible to perform the corresponding I/O operation (e.g., read(2)) without blocking.

最佳答案

Select() 不知道您要尝试写入多少字节,它只知道套接字的传出数据缓冲区未满。

如果您希望 write() 不阻塞,请将套接字设置为非阻塞模式。

关于python - tcp 套接字,select 告诉可写,但 write() 会阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20233030/

相关文章:

python - TypeError : mean() got an unexpected keyword argument 'dtype' # Pandas. 数据帧

c - 为什么零长度 VLA UB?

c - 从字符串中获取标记(stdin)

perl - Perl中套接字编程中的问题

python - 使用 numpy 数组/列表作为字符串的索引

python - 如何在 python Pyramid 应用程序中获取服务主机和端口?

python - Python Selenium 中的多个滚动条

c - 将指针的值分配给其他指针时,只读位置分配错误?

sockets - 如何关闭等待服务器套接字监听的任务?

php - ReCaptcha - 无法打开套接字