用John Nagle算法最小化报文传输延时
通过 TCP socket 进行通信时,数据都拆分成了数据块,放到一个TCP报文中为了达到最好的性能,总希望尽可能多的可用数据来填充每个报文已达到为最大报文段长度(maximum segment size 或MSS)。当没有足够的数据来填充 payload 时,TCP 就会采用 Nagle 算法自动将一些小的缓冲区连接到一个报文段中。这样可以通过最小化所发送的报文的数量来提高应用程序的效率,并减轻整体的网络拥塞问题。
但这导致了数据收发的延时,特别是当一端连续发送多个小型数据,然后读响应时,多个发送的数据会被 Nagle 算法整合成一个包然后发送,这样会造成大量读写socket请求时收发缓慢(比如本地机器1秒收发几十个请求/响应)。如果需要最小化传输延时,可以设置 TCP_NODELAY socket 选项以禁用 Nagle 算法,如下:
int sock, flag, ret;
/* Create new stream socket */
sock = socket( AF_INET, SOCK_STREAM, 0 );
/* Disable the Nagle (TCP No Delay) algorithm */
flag = 1;
ret = setsockopt( sock, IPPROTO_TCP, TCP_NODELAY, (void *)&flag, sizeof(flag) );
if (ret == -1) {
       printf("Couldn't setsockopt(TCP_NODELAY)/n");
       exit(-1);
}
经测试,简单的本地收发动作可以达到1秒30000次,效率提升了数千倍。当然在非本地机器环境下不可能提升这么多^_^。

二、减少系统调用 提高I/O效率
任何时候通过一个 socket 来读写数据时,您都是在使用一个系统调用(system call)。这个调用(例如 read 或 write)跨越了用户空间应用程序与内核的边界。另外,在进入内核之前,您的调用会通过 C 库来进入内核中的一个通用函数(system_call())。从 system_call() 中,这个调用会进入文件系统层,内核会在这儿确定正在处理的是哪种类型的设备。最后,调用会进入 socket 层,数据就是在这里进行读取或进行排队从而通过 socket 进行传输的(这涉及数据的副本)。
这个过程耗费的资源很高,因此调用次数越多,通过这个调用链进行的工作所需要的时间就越长,应用程序的性能也就越低。我们无法避免这些系统调用,但我们可以最

小化的使用这些调用。
在将数据读/写一个 socket 时,尽量一次读/写所有的数据,而不是执行多次读/写数据的操作:
write( sockfd, data1, ...);
write( sockfd, data2, ...);
write( sockfd, data3, ...);
read( sockfd, response, ...);
read( sockfd, result, ...);
改为
snprintf( data, format, .... );
write( sockfd, data, ...);
read( sockfd, result, ...);
// get response and handle result

三、调节合适的TCP发送/接收缓冲区
TCP 的性能取决于几个方面的因素。两个最重要的因素是链接带宽(link bandwidth)(报文在网络上传输的速率)和 往返时间(round-trip time) 或 RTT(发送报文与接收到另一端的响应之间的延时)。这两个值确定了称为 Bandwidth Delay Product(BDP)的内容:
BDP = link_bandwidth * RTT
带宽可以从网卡信息查看,RTT可以通过ping获取平均值。BDP决定了TCP滑动窗口的大小,即socket的发送接收缓冲区的大小。
如果应用程序是通过一个 100Mbps 的局域网进行通信,其 RRT 为 50 ms,那么 BDP 就是:
100MBps * 0.050 sec / 8 = 0.625MB = 625KB      此处除以 8 是将位转换成通信使用的字节。
因此,我们可以将 TCP 窗口设置为 BDP 或 1.25MB(2*625k)。
通过设置SO_RCVBUF和SO_SNDBUF,可以达到改变发送接收缓冲区大小的目的:
ret = getsockopt( sockfd, SOL_SOCKET, SO_SNDBUF,
                       (void *)&original, sizeof(original) );
if(....){
ret = setsockopt( sockfd, SOL_SOCKET, SO_SNDBUF
                       (void *)&new, sizeof(new) );
}

当然也可以设置系统的缓冲区,比如:
echo "8192 9000000 12000000" > /proc/sys/net/ipv4/tcp_wmem

Unix网络编程 提高 TCP I/O 性能的3点经验相关推荐

  1. UNIX网络编程——解决TCP网络传输“粘包”问题

           当前在网络传输应用中,广泛采用的是TCP/IP通信协议及其标准的socket应用开发编程接口(API).TCP/IP传输层有两个并列的协议:TCP和UDP.其中TCP(transport ...

  2. 【Unix 网络编程】TCP状态转换图详解

    TCP协议的三路握手和四次挥手.如下图所示,TCP通信过程包括三个步骤:建立TCP连接通道(三次握手).数据传输.断开TCP连接通道(四次挥手). 这里进一步探究TCP三路握手和四次挥手过程中的状态变 ...

  3. UNIX网络编程——基本TCP套接字编程 【转贴】

    一.基于TCP协议的网络程序 下图是基于TCP协议的客户端/服务器程序的一般流程: 服务器调用socket().bind().listen()完成初始化后,调用accept()阻塞等待,处于监听端口的 ...

  4. unix网络编程各种TCP客户-服务器程序设计实例(三)

    第五种  TCP预先派生子进程服务器程序: 对预先派生子进程服务器的最后一种改动就是由父进程调用accept,然后再将所接受的已连接描述字传递给子进程.父进程必须跟踪子进程的忙闲状态,以便给空闲子进程 ...

  5. 《UNIX网络编程 卷1:套接字联网API》学习笔记——基本TCP套接字编程

    UNIX网络编程--基本TCP套接字编程 socket 函数 connect 函数 bind 函数 listen 函数 accept 函数 fork 和 exec 函数 并发服务器 close 函数 ...

  6. 《UNIX网络编程 卷1:套接字联网API(第3版)》——第2章 传输层:TCP、UDP和SCTP 2.1概述...

    本节书摘来自异步社区<UNIX网络编程 卷1:套接字联网API(第3版)>一书中的第2章,第2.1节,作者:[美]W. Richard Stevens , Bill Fenner , An ...

  7. unix网络编程之简介和运输层TCP/UDP

    前言:本文只介绍了有关UNIX网络编程的理论知识,具体的应用和例子在稍后的博文中将更新 第一章  简介 一个简单的服务器程序步骤: 说明:1.创建TCP套接口 2.捆绑服务器的众所周知端口 3.把套接 ...

  8. UNIX网络编程卷1 回射客户程序 TCP客户程序设计范式

    本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 下面我会介绍同一个使用 TCP 协议的客户端程序的几个不同版本,分别是停等版本.select ...

  9. 网编编程必看书籍:unix网络编程

    unix网络编程被誉为圣经,该书主要讲socket套接字相关,socket API,从底层剖析网络编程.网络编程中需要用到的一些经典函数,多路复用函数,这些都值得去反复学习研究. 目录: 录 Part ...

最新文章

  1. [***]HZOJ 跳房子
  2. jenkins学习笔记2-在centos中安装jenkins master测试环境
  3. hadoop安装hive及配置mysql_Hadoop系列之Hive(数据仓库)安装配置
  4. jquery 获取 A 标签 超级链接属性
  5. 【UVA - 11729】Commando War (贪心,时间调度问题)
  6. Python最常用的函数、基础语句有哪些?你都知道吗
  7. 怎么更好掌握Web前端技术?JS的跨域是怎么回事?
  8. 【深拷贝VS浅拷贝】------【巷子】
  9. Java学习路线图(如何快速学Java)
  10. word2013论文公式居中并且自动编号
  11. 从BIO到NIO的网络通信
  12. 回溯法 | 图的m着色问题
  13. 独立IP、特产浏览量(PV)、访问次数(VV)、独立访客(UV)
  14. STM32标准库修改HSI时钟教程
  15. 《人月神话(The Mythical Man-Month)》2人和月可以互换吗?人月神话存在吗?
  16. DIY自平衡车意外失去左腿后,小哥爆改假肢玩出了花,稚晖君:技术到内心都硬核...
  17. 如何选择CDN?你需要关注这三个方面
  18. nginx反向代理非80端口/nginx反代非80端口
  19. 自然二进制与格雷码的转换
  20. stm32建立标准的工程模板

热门文章

  1. linux6用户t密码,linux系统 用户和组管理类命令的使用方法
  2. 如何将风险应用加入白名单_将微信服务器、API接口的IP列表加入宝塔防火墙IP白名单...
  3. oracle正在没落,Oracle停掉一个正在运行的job
  4. ArcGIS Engine10.4版本
  5. ping 攻击 Linux,Linux 环境实现ping攻击
  6. CStopwatch详细用法
  7. 三栏布局 五中解决方式
  8. 4 . 2 存储系统
  9. 44.作用域,局部和全局变量
  10. js:如何在循环异步请求的每次返回中添加想要的值