当前位置: 首页 > 编程日记 > 正文

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 }

转载于:https://www.cnblogs.com/jiangu66/archive/2013/04/11/3015617.html

相关文章:

不用任何第三方,写一个RTMP直播推流器

2016年是移动直播爆发年&#xff0c;不到半年的时间内无数移动直播App掀起了全民直播的热潮。然而个人觉得直播的门槛相对较高,从推流端到服务端器到播放端&#xff0c;无不需要专业的技术来支撑&#xff0c;仅仅推流端就有不少需要学习的知识。目前大部分直播采用的都是RTMP协…

手机连接服务器数据库文件,手机连接服务器数据库文件夹

手机连接服务器数据库文件夹 内容精选换一换GaussDB(DWS)支持使用gs_dump工具导出某个数据库级的内容&#xff0c;包含数据库的数据和所有对象定义。可根据需要自定义导出如下信息&#xff1a;导出数据库全量信息&#xff0c;包含数据和所有对象定义。使用导出的全量信息可以创…

开源一个上架 App Store 的相机 App

原创 2017-02-21 伯乐专栏/陈浩 iOS大全&#xff08;点击上方公众号&#xff0c;可快速关注&#xff09; 来源&#xff1a;伯乐在线 - Hawk0620 如有好文章投稿&#xff0c;请点击 → 这里了解详情 如需转载&#xff0c;发送「转载」二字查看说明 Osho 相机是我独立开发上架的…

WIN7下,联想A30T通过USB连接上网

1.手机连接3G信号 2.手机上在设置里 "设置" |"应用程序" |"USB模式" |勾选"网卡模式" 3.连接上Win7,会出现驱动安装程序,手动安装这里的驱动.(驱动在百度网盘:) 4.在设备管理,网络适配器里查看驱动是否安装成…

在bootstrap ace样式框架上修改的后台管理型模板(Tab页后台管理模板)

后台管理模板开始用frameset布局&#xff0c;但是有时候会遮挡比如上面导航或者左边导航的二级三级弹出菜单&#xff0c;因为宽度被限制了&#xff0c;所以有时候就用easyui或者ext的&#xff0c;但是样式不好看&#xff0c;然后看到了bootstrap ace的后台管理模板&#xff0c;…

文件服务器的内存要多少,文件服务器内存要多大

文件服务器内存要多大 内容精选换一换Windows场景中&#xff0c;当把源端服务器迁移到华为云后&#xff0c;目的端服务器C盘的已用空间比对应源端服务器C盘的已用空间大至少1GB&#xff0c;而不是与源端服务器C盘的已用空间一致&#xff0c;这正常吗&#xff1f;正常现象。您可…

好玩的 RAC

UIControl 监听 control 点击 从此告别 addTarget 和 btnClick 1234[[self.loginBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(UIButton *btn) {// btn, 即 self.loginBtn// 这里执行点击之后的操作}];UITextField 监听 textField 的 text 改…

机器学习简单代码示例

机器学习简单代码示例 //在gcc-4.7.2下编译通过。 //命令行&#xff1a;g -Wall -ansi -O2 test.cpp -o test #include <iostream> using namespace std; void input(int &oper,const bool meth) {//meth为true则只判断1&#xff0c;为false则判断1或0while(true){ci…

【2007-5】【素数算式】

Description 在下面的算式中每个“#”都表示一个素数数字。##* #————###请编写程序确定这些数字&#xff0c;输出所有的解。Input Output 依次打印输出每一种解&#xff0c;每行表示一种解&#xff0c;格式为&#xff1a;##*# ###。Sample Input Sample Output HINT Sou…

ubuntu服务器版编辑文件,Ubuntu 服务器版 18.04.4 固定 IP 设置

1、输入命令 su 以root用户权限操作2、找到Ubuntu网络配置文件vim /etc/netplan/50-cloud-init.yaml3、输入 i 让文件变成可编辑状态4、修改内容dhcp4: nodhcp4: noaddresses: [192.168.3.50/24]gateway4: 192.168.3.1nameservers:addresses: [8.8.8.8, 8.8.4.4]如图&#xff…

RACCommand 粗解

前言 学习 RAC 的过程中&#xff0c;RACCommand 是我一直很迷惑的点&#xff0c;感觉一直抓不到它的要点&#xff0c;不明白为何要这样使用。曾经想过用别的方法来替代&#xff0c;只要能找到替代的方法&#xff0c;暂时就没必要死磕&#xff0c;结果发现避免不了&#xff0c;那…

将整数拆分为2的幂次方

任意一个正整数都可以用2的幂次方表示&#xff0c;例如&#xff1a;137&#xff1d;2^72^32^0&#xff0c;同时约定次方用括号来表示&#xff0c;即a^b&#xff1d;a(b)。由此可知&#xff0c;137可表 示&#xff1a;2(7)2(3)2(0)。进一步&#xff1a;72^222^0(2^1用2表示)&…

vbs脚本在服务器上虚拟按键,iisvdir.vbs iis虚拟目录管理脚本使用介绍

IIS管理器也是通过调用iisvdir.vbs来实现虚拟目录的创建和删除的。我们可以通过命令行的方式来执行iisvdir.vbs脚本1)创建虚拟目录&#xff1a;cscript c:\windows\system32\iisvdir.vbs [/s server] [/u username /p password] /create [virtualRoot] Alias PhysicalPath2)删除…

Python字典部分源码分析,字典是无序的

1 def clear(self): # real signature unknown; restored from __doc__ 2 """ D.clear() -> None. Remove all items from D. """ 3 pass 1 #练习1、清空字典&#xff08;置空&#xff09; 2 li {"key1":"v…

【2011-3】【旋转表格】

Description 小敏是个数学迷&#xff0c;特别擅长加法与除法。老师给他一个问题&#xff0c;有一个22表格&#xff0c;表中有正整数A, B, C 和D&#xff0c;表格和表格值的计算如下&#xff1a;小敏的任务是对给出的表格每次顺时针旋转90度&#xff0c;使旋转后的表格值最大&am…

iOS-FXDanmaku弹幕库介绍、相关技术分享

前言 去年, 2016年, 一大波直播平台在移动端涌出, 直播慢慢步入了人们的视角. 网上如今能够看到各式各样的直播, 如秀场直播、游戏直播、体育直播、娱乐直播等等. 在各种类型的直播中, 弹幕在PC、移动端都几乎成为了标配, 今天在这里主要介绍一下个人开源的iOS弹幕, 以及提前为…

【廖雪峰Python学习笔记】字符串与编码

字符串与编码 三种字符编码 ASCII编码 &#xff1a;计算机由美国人发明&#xff0c;最早只有127个字符编码—— 大小写英文字母、数字和符号Unicode&#xff1a;把中文、日文、韩文等所有语言统一到一套编码中&#xff0c;2-4byte&#xff0c;现代OS和大多数语言都支持utf-8&a…

application

说明: 进行应用级操作.比如:设置提醒框,打开其他应用,显示联网状态,控制状态栏 单例对象, UIApplication *app[UIApplication sharedApplication];常用方法 方法1:设置app图标数字提示信息//设置app图标数字提示信息app.applicationIconBadgeNumber10;//ios8以后需要实现以下方…

博客园2013年4月份第2周源码发布详情

Silk Navigation for ASP.NET源码 2013-4-12 [VS2010]功能介绍&#xff1a;Silk Navigation 微软提供&#xff0c;为构建cross-browser 的Web应用程序&#xff0c;是用ASP.NET MVC3和jQuery的。它是非常简单使用ASP.NET Web窗体构建&#xff0c;从而在一个相当小的&#xff0c…

iOS 静态库封装

静态库和动态库 静态库和动态库存在形式 静态库&#xff1a;以.a 和 .framework为文件后缀名。动态库&#xff1a;以.tbd(之前叫.dylib) 和 .framework 为文件后缀名。 静态库和动态库的区别 静态库&#xff1a;链接时会被完整的复制到可执行文件中&#xff0c;被多次使用就有多…

【廖雪峰Python学习笔记】list tuple dict set

列表元组字典集合创建l [1, ‘a’, [1, 3], True]t (1, )d {‘key’ : ‘value’}s set([1, 2, 4, 2, 1])索引l[1]t[0]d.get(‘key’)/插入l.insert(1, ‘3’) / l.append(‘4’)/d[‘k1’] ‘v1’s.add(‘9’)修改l[0] 4/d[‘k1’] v/移除l.pop(0)/d.pop(‘k1’)s.remo…

响应式布局简明示例

响应式布局简明示例&#xff0c;响应式布局最好同时也是自适应布局&#xff0c;然后再配合css3媒体查询&#xff0c;来达到完美的响应式布局。css3的媒体查询ie9一下是不支持的&#xff0c;这太遗憾了&#xff0c;不过幸运的是有大神已经为前端屌丝们写好了用于IE9以下的媒体查…

iOS - APP任意push新页面那些事

大家都知道&#xff0c;UINavigationController对象有一个方法pushViewController&#xff0c;用来做视图跳转&#xff0c;也是在iOS开发中常用的页面转换方法之一。大多数APP的结构一般都是&#xff0c;使用一个UITabBarController&#xff0c;每个tab上都是一个UINavigationC…

主攻ASP.NET.4.5 MVC4.0之重生:Entity Framework生成实体类步骤(十三)

1.新建一个ASP.NET MVC 4.0 项目 2.安装Entity Framework Power Tools 3.Entity Framework- -RepositoryReverse Engineer Code First 4.Install-Package EntityFramework or Update-Package EntityFramework PM -Repository Install-Package EntityFramework 已安装“EntityFr…

【廖雪峰Python学习笔记】高阶函数

Higher-order function高阶函数映射过滤算法排序算法高阶函数 变量可指向函数 >>> abs # 函数 <built-in function abs> >>> abs(-0) # 函数调用 0 >>> func abs # 变量可指向函数 >>> func(-9) # 调用变量 调用函数 9函数名…

丁贵才130702010042第二次作业

第二次作业 2.9 设有如下语句&#xff0c;请用相应的谓词公式分别把它们表示出来&#xff1a; &#xff08;1&#xff09;有的人喜欢梅花&#xff0c;有的人喜欢菊花&#xff0c;有的人既喜欢梅花有喜欢梅花。 解&#xff1a;定义谓词 P&#xff08;x&#xff09;&#xff1a;x…

SpringMVC @RequestBody接收Json对象字符串

以前&#xff0c;一直以为在SpringMVC环境中&#xff0c;RequestBody接收的是一个Json对象&#xff0c;一直在调试代码都没有成功&#xff0c;后来发现&#xff0c;其实 RequestBody接收的是一个Json对象的字符串&#xff0c;而不是一个Json对象。然而在ajax请求往往传的都是Js…

【iOS】自定义日期选择器

自定义了一个日期选择器&#xff0c;与大家分享一下&#xff0c;期待宝贵建议。 github下载地址&#xff1a;https://github.com/huahua0809/XHDatePicker 下面只是说明一下怎么用&#xff0c;具体实现请下载代码看看&#xff1b; 如果大家觉得这个分享有所帮助的话&#xff0c…

【廖雪峰Python学习笔记】函数式编程

Functional Programming高阶函数返回函数匿名函数装饰器偏函数高阶函数 面向过程的程序设计&#xff1a; 把大段代码拆成函数&#xff0c;通过一层层函数调用&#xff0c;可将复杂任务分解成若干简单的任务函数是面向过程的程序设计的基本单位计算机Computer && 计算c…

asp 随机读取ID之Access

我在用ASP连接access 这个桌面数据库的时候&#xff0c;有时候要随机读取ID&#xff0c;传统的办法是&#xff1a; select top 3 * from tablename order by Rnd(ID) 但这样不行&#xff0c;默认还是按ID排序。 解决办法加上timer() 这个函数 select top 3 * from tablenam…