zoukankan      html  css  js  c++  java
  • socket编程缓冲区大小对send()的影响

    1. 概述

    Socket编程中,使用send()传送数据时,返回结果受到以下几个因素的影响:
    • Blocking模式或non-blocking模式
    • 发送缓冲区的大小
    • 接收窗口大小
    本文档介绍通过实验的方式,得出(收发)缓冲区大小对send结果的影响。实验使用C语言。

    2 数据发送和接收的过程

    如下图所示,程序调用send()发送数据时,数据将首先进入发送缓冲区,等待发送。系统底层socket负责数据的传送,数据通过网络到达接收方的缓冲区。接收方缓冲区内的数据,等待应用程序调用recv()读取。


    3 实验一:Blocking模式下

    3.1 实验步骤

    发送端:blocking模式send()发送8192字节,使用setsockopt设置SO_SNDBUF改变发送缓冲区的大小。
    接收端:建立连接后进入睡眠。使用setsockopt设置SO_RCVBUF改变接收缓冲区的大小。

    3.2 实验得到的数据

     

     3.3实验结论

    “已发送字节 + 缓冲区中待发送字节 > 总字节”时,send()能立即返回,否则处于阻塞等待。

    4 实验二:Non-Blocking模式下

    4.1 实验步骤

    发送端:non-blocking模式send()发送8192字节,使用setsockopt设置SO_SNDBUF改变发送缓冲区的大小。
    接收端:建立连接后进入睡眠。使用setsockopt设置SO_RCVBUF改变接收缓冲区的大小。

    4.2 实验数据

     

    4.3 实验结论

    随着SNDBUF增大,send()返回已发送字节越大。接收窗口大小对结果影响不是线性的。实际已接收的只有窗口大小。

    5. 实验原代码

    5.1 服务器端代码

      1 #include <netinet/in.h>
      2 #include <sys/socket.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <stdint.h>
      6 #include <string.h>
      7 #include <errno.h>
      8 
      9 int
     10 init_server(int type, const struct sockaddr_in *addr)
     11 {
     12     int fd;
     13     int err = 0;
     14     int reuse = 1;
     15 
     16     if ((fd = socket(AF_INET, type, 0)) < 0) {
     17         printf("Failed to create socket.\n");
     18         exit(1);
     19     }
     20     if (bind(fd, (struct sockaddr *)addr, sizeof(*addr)) < 0) {
     21         printf("Server Bind Failed: %d\n", errno);
     22         exit(1);
     23     }
     24     if (listen(fd, 5) < 0) {
     25         printf("Fail to listen\n");
     26         exit(1);
     27     }
     28     return fd;
     29 }
     30 
     31 void
     32 serve(int fd, int n_to_send, int s_buf_size, int flag)
     33 {
     34     int clfd, clfd_2;
     35     struct sockaddr_in client_addr;
     36     char *buf;
     37     const char  *addr;
     38     socklen_t alen = sizeof(int);
     39     int n=0;
     40     int i;
     41     ssize_t num;
     42 
     43     /* initialize the send buffer */
     44     buf = malloc(n_to_send * sizeof(char));
     45     for (i = 0; i < n_to_send; i++)
     46         buf[i] = '=';
    47 
     48     /* change the send buffer size */
     49     getsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&n, &alen);
     50     printf("SEND buffer size: %d\n", n);
     51     getsockopt(fd, SOL_SOCKET, SO_SNDLOWAT, (char *)&n, &alen);
     52     printf("SEND LOWAT size: %d\n", n);
     53     if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&s_buf_size, sizeof(int)) < 0) {
     54         printf("fail to change SNDbuf.\n");
     55         exit(2);
     56     }
     57     getsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&n, &alen);
     58     printf("Current SEND buffer size: %d\n", n);
     59 
     60     /* loop: accept a client, and send buffer to it */
     61     while(1) {
     62         printf("waiting for clients...\n");
     63         clfd = accept(fd, (struct sockaddr*)&client_addr, &alen);
     64         if(clfd < 0) {
     65             printf("accept error.");
     66             exit(4);
     67         }
     68         printf("new client\n");
     69         printf("Sending %d bytes...\n", n_to_send);
     70         i = send(clfd, buf, n_to_send, flag);
     71         printf("send %d bytes.\n", i);
     72         close(clfd);
     73         printf("\n\n");
     74     }
     75 }
     76 
     77 int
     78 main(int argc, char *argv[])
     79 {
     80     char host[] = "127.0.0.1";
     81     struct sockaddr_in server_addr;
     82     uint32_t s_addr;
     83     int fd;
     84     int n_to_send, s_buf_size, flag;
     85 
     86     if (argc != 4) {
     87         printf("useage %s <num to send> <send buf size> <wait_flag:1|0>\n", argv[0]);
     88         exit(1);
     89     }
     90     n_to_send = atoi(argv[1]);
     91     s_buf_size = atoi(argv[2]);
    92     flag = atoi(argv[3]) ? 0 : MSG_DONTWAIT;
     93 
     94     bzero(&server_addr, sizeof(server_addr));
     95     inet_pton(AF_INET, host, &s_addr);
     96     server_addr.sin_family = AF_INET;
     97     server_addr.sin_addr.s_addr = s_addr;
     98     server_addr.sin_port = htons(9000);
     99 
    100     fd = init_server(SOCK_STREAM, &server_addr);
    101     serve(fd, n_to_send, s_buf_size, flag);
    102 
    103     exit(0);
    104 }

    5.2 客户端代码

      1 #include <netinet/in.h>
      2 #include <unistd.h>
      3 #include <errno.h>
      4 #include <sys/socket.h>
      5 #include <stdio.h>
      6 #include <stdlib.h>
      7 #include <string.h>
      8 #include <stdint.h>
      9 
     10 #define SLEEP_TIME 120
     11 
     12 void
     13 tcp_client(int sockfd, struct sockaddr_in *s_addr, int r_buf_size)
     14 {
     15     int n, i;
     16     socklen_t slen = sizeof(int);
     17     int rcv_len;
     18 
     19     /* change receiving buffer size */
     20     getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &rcv_len, &slen);
     21     printf("Receive buffer size: %d\n", rcv_len);
     22     setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &r_buf_size, sizeof(int));
     23     getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &rcv_len, &slen);
     24     printf("Current Receive buffer size: %d\n", rcv_len);
     25 
     26     /* connect to server */
     27     if(connect(sockfd, (struct sockaddr*)s_addr, sizeof(*s_addr))) {
     28         printf("Can not connect to server.\n");
     29         exit(2);
     30     }
     31 
     32     sleep(SLEEP_TIME);
     33 }
     34 
     35 int
     36 main(int argc, char *argv[])
     37 {
     38     char server_ip[] = "127.0.0.1";
     39     int port = 9000;
     40     uint32_t s_addr;
     41     int s_fd;
     42     struct sockaddr_in server_addr;
     43     int r_buf_size;
     44 
     45     if (argc != 2) {
     46         printf("usage: %s <recv_buf_size>\n", argv[0]);
    47         exit(1);
     48     }
     49     r_buf_size = atoi(argv[1]);
     50 
     51     bzero(&server_addr, sizeof(server_addr));
     52     inet_pton(AF_INET, server_ip, &s_addr);
     53     server_addr.sin_family = AF_INET;
     54     server_addr.sin_addr.s_addr = s_addr;
     55     server_addr.sin_port = htons(port);
     56     if ((s_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
     57         printf("Fail to create socket.");
     58         exit(1);
     59     }
     60 
     61     tcp_client(s_fd, &server_addr, r_buf_size);
     62     exit(0);
     63 }

  • 相关阅读:
    Atitit (Sketch Filter)素描滤镜的实现  图像处理  attilax总结v2
    JS设置cookie、读取cookie、删除cookie
    Atitit 图像处理30大经典算法attilax总结
    Atitit数据库层次架构表与知识点 attilax 总结
    Atitit 游戏的通常流程 attilax 总结 基于cocos2d api
    Atitti css transition Animation differ区别
    Atitit 图像清晰度 模糊度 检测 识别 评价算法 源码实现attilax总结
    Atitit 全屏模式的cs桌面客户端软件gui h5解决方案 Kiosk模式
    Atitit 混合叠加俩张图片的处理 图像处理解决方案 javafx blend
    Atitit  rgb yuv  hsv HSL 模式和 HSV(HSB) 图像色彩空间的区别
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3015617.html
Copyright © 2011-2022 走看看