简体   繁体   English

tcp套接字,选择表明可写,但是write()块

[英]tcp socket, select tells writable, but write() blocks

I wrote a little tcp socket server program, using select() to check if a client socket is writable. 我编写了一个小小的tcp套接字服务器程序,使用select()检查客户端套接字是否可写。 If the client is writable, I will write data to it. 如果客户端可写,我将向其写入数据。

The client is written in Python, for testing only, it connect to the server, and never read from the connect. 客户端使用Python编写,仅用于测试,它连接到服务器,从不读取连接内容。

The result is, server write() finally blocks. 结果是,服务器write()最终阻塞。

Server(C): 服务器(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;
}

Client(Python): 客户端(Python):

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

Output: 输出:

$ 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

My qustion is: why would write() operation blocks even if select tells writable? 我的问题是: 即使select告诉可写,为什么write()操作也会阻塞? The manual of select() says: select()的手册说:

A file descriptor is considered ready if it is possible to perform the corresponding I/O operation (eg, read(2)) without blocking. 如果可以执行相应的I / O操作(例如read(2))而不会阻塞,则认为文件描述符已准备就绪。

Select() doesnt know how many bytes you are going to try to write, it only knows that the socket's outgoing-data buffer isn't full. Select()不知道您要尝试写入多少字节,它仅知道套接字的传出数据缓冲区未满。

If you want write() not to block, set the socket to non-blocking mode. 如果不希望write()阻塞,请将套接字设置为非阻塞模式。

接收方的TCP缓冲区最终将被发送方发送的数据填充,以便通告一个零尺寸的窗口,以通知发送方“我没有剩余空间来保存数据,请立即停止”。

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

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