几个结论:

1. linux查看tcp缓冲区参数命令:

cat /proc/sys/net/ipv4/tcp_wmem  # 写缓冲区大小
4096 16384 4194304 # 分别表示最小值,默认值,最大值

cat /proc/sys/net/ipv4/tcp_rmem # 读缓冲区大小
4096 87380 6291456 # 同上

其中默认值只是一个参考值,操作系统基本都会动态设置读写缓冲区的大小,且在每一次的recv或send操作之后,都有可能调整缓冲区大小。

 

2. 阻塞式的send操作在写缓冲区剩余大小不足时,会一直等待。如果对方主动断开,阻塞的send会返回errno为104的复位标志。非阻塞的send会有多少空间就往里copy多少数据,没有空间则返回errno标志。

 

3. 通过recv()函数的MSG_PEEK标志可以大约知道读缓冲区有多少数据;通过ioctl(tcp_socket, SIOCOUTQ, &value)可以知道写缓冲区还有多少数据没发出去。

 

 

server端代码:

int main() {
       // ...
       // 建立listen端口的一些基本步骤
 
        struct sockaddr_in client_addr;
        memset(&client_addr, 0, sizeof(client_addr));
        socklen_t client_len = sizeof(client_addr);
        int new_client_sock = accept(listen_sock, (struct sockaddr *)&client_addr, &client_len);

        char client_ipv4_str[INET_ADDRSTRLEN];
        inet_ntop(AF_INET, &client_addr.sin_addr, client_ipv4_str, INET_ADDRSTRLEN);
        printf("Incoming connection from %s:%d.\n", client_ipv4_str, client_addr.sin_port);
        int val;
        int len = sizeof(val);
        getsockopt(new_client_sock, SOL_SOCKET, SO_RCVBUF, (void *)&val, (socklen_t*)&len);
        printf("size:%d\n", val);

        while (1) {
            sleep(1);
        }
 }

client:

int main() {
    // 。。。
    // 建立连接的一些步骤
    int val;
    int len = sizeof(val);
    getsockopt(clientfd, SOL_SOCKET, SO_SNDBUF, (void *)&val, (socklen_t*)&len);
    printf("size:%d\n", val);

    char buf[2626570];
    while (1) {
    printf("here\n");
        int size = send(clientfd, buf, 2626570, 0);
        printf("send size:%d\n", size);
        if (size < 0)
          printf("failed.  %d,  %d,  $s\n", size, errno, strerror(errno));
    getsockopt(clientfd, SOL_SOCKET, SO_SNDBUF, (void *)&val, (socklen_t*)&len);
    printf("size:%d\n", val);
        sleep(5);
    }
    while (1) {
        sleep(1);
    }  
}

 

posted on 2020-11-19 22:53  SimbaStar  阅读(1122)  评论(0编辑  收藏  举报