以前一些没有注意到的问题都成为了性能瓶颈,通过设置一些TCP/IP选项能够解决一部分问题,当然根本的解决方法是重构代码,重新设计服务器框架。先列出几个TCP/IP选项:
选项 man 7 socket: SO_REUSEADDR SO_RECVBUF/SO_SNDBUF SO_KEEPALIVE SO_LINGER
man 7 tcp: TCP_CORK TCP_NODELAY TCP_DEFER_ACCEPT TCP_KEEPCNT/TCP_KEEPIDLE/TCP_KEEPINTVL
SO_REUSEADDR 在服务器程序中,SO_REUSEADDR socket选项通常在调用bind()之前被设置。 SO_REUSEADDR可以用在以下四种情况下。 (摘自《Unix网络编程》卷一,即UNPv1) 1、当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时,而你启动的程序的socket2要占用该地址和端口,你的程序就要用到该选项。 2、SO_REUSEADDR允许同一port上启动同一服务器的多个实例(多个进程)。但每个实例绑定的IP地址是不能相同的。在有多块网卡或用IP Alias技术的机器可以测试这种情况。 3、SO_REUSEADDR允许单个进程绑定相同的端口到多个socket上,但每个socket绑定的ip地址不同。这和2很相似,区别请看UNPv1。 4、SO_REUSEADDR允许完全相同的地址和端口的重复绑定。但这只用于UDP的多播,不用于TCP。
TCP_NODELAY/TCP_CHORK TCP_NODELAY和TCP_CORK基本上控制了包的“Nagle化”,Nagle化在这里的含义是采用Nagle算法把较小的包组装为更大的帧。TCP_NODELAY和TCP_CORK都禁掉了Nagle算法,只不过他们的行为不同而已。 TCP_NODELAY 不使用Nagle算法,不会将小包进行拼接成大包再进行发送,直接将小包发送出去,会使得小包时候用户体验非常好。 当在传送大量数据的时候,为了提高TCP发送效率,可以设置TCP_CORK,CORK顾名思义,就是"塞子"的意思,它会尽量在每次发送最大的数据量。当设置了TCP_CORK后,会有阻塞200ms,当阻塞时间过后,数据就会自动传送。
详细的资料可以查看参考文献5。
SO_LINGER linger,顾名思义是延迟延缓的意思,这里是延缓面向连接的socket的close操作。默认,close立即返回,但是当发送缓冲区中还有一部分 数据的时候,系统将会尝试将数据发送给对端。SO_LINGER可以改变close的行为。控制SO_LINGER通过下面一个结构: struct linger { int l_onoff; /*0=off, nonzero=on*/ int l_linger; /*linger time, POSIX specifies units as seconds*/ };
通过结构体中成员的不同赋值,可以表现为下面几种情况: 1. l_onoff设置为0,选项被关闭。l_linger值被忽略,就是上面的默认情形,close立即返回。 2. l_onoff设置为非0,l_linger被设置为0,则close()不被阻塞立即执行,丢弃socket发送缓冲区中的数据,并向对端发送一个RST报文。这种关闭方式称为“强制”或“失效”关闭。 3. l_onoff设置为非0,l_linger被设置为非0,则close()调用阻塞进程,直到所剩数据发送完毕或超时。这种关闭称为“优雅的”关闭。
注意: 这个选项需要谨慎使用,尤其是强制式关闭,会丢失服务器发给客户端的最后一部分数据。UNP中: The TIME_WAIT state is our friend and is there to help us(i.e., to let the old duplicate segments expire in the network).
TCP_DEFER_ACCEPT defer accept,从字面上理解是推迟accept,实际上是当接收到第一个数据之后,才会创建连接。对于像HTTP等非交互式的服务器,这个很有意义,可以用来防御空连接攻击(只是建立连接,但是不发送任何数据)。 使用方法如下:
val = 5; setsockopt(srv_socket->fd, SOL_TCP, TCP_DEFER_ACCEPT, &val, sizeof(val)) ; |
里面 val 的单位是秒,注意如果打开这个功能,kernel 在 val 秒之内还没有收到数据,不会继续唤醒进程,而是直接丢弃连接。如果服务器设置TCP_DEFER_ACCEPT选项后,服务器受到一个CONNECT请求 后,三次握手之后,新的socket状态依然为SYN_RECV,而不是ESTABLISHED,操作系统不会Accept。
由于设置TCP_DEFER_ACCEPT选项之后,三次握手后状态没有达到ESTABLISHED,而是SYN_RECV。这个时候,如果客户端一直没 有发送"数据"报文,服务器将重传SYN/ACK报文,重传次数受net.ipv4.tcp_synack_retries参数控制,达到重传次数之后, 才会再次进行setsockopt中设置的超时值,因此会出现SYN_RECV生存时间比设置值大一些的情况。
关于SYN_RECV状态可以查看参考文献7。
SO_KEEPALIVE/TCP_KEEPCNT/TCP_KEEPIDLE/TCP_KEEPINTVL
如果一方已经关闭或异常终止连接,而另一方却不知道,我们将这样的TCP连接称为半打开的。TCP通过保活定时器(KeepAlive)来检测半打开连接。
在高并发的网络服务器中,经常会出现漏掉socket的情况,对应的结果有一种情况就是出现大量的CLOSE_WAIT状态的连接。这个时候,可以通过设置KEEPALIVE选项来解决这个问题,当然还有其他的方法可以解决这个问题,详细的情况可以查看参考资料8。
使用方法如下:
//Setting For KeepAlive int keepalive = 1; setsockopt(incomingsock,SOL_SOCKET,SO_KEEPALIVE,(void*)(&keepalive),(socklen_t)sizeof(keepalive)); int keepalive_time = 30; setsockopt(incomingsock, IPPROTO_TCP, TCP_KEEPIDLE,(void*)(&keepalive_time),(socklen_t)sizeof(keepalive_time)); int keepalive_intvl = 3; setsockopt(incomingsock, IPPROTO_TCP, TCP_KEEPINTVL,(void*)(&keepalive_intvl),(socklen_t)sizeof(keepalive_intvl)); int keepalive_probes= 3; setsockopt(incomingsock, IPPROTO_TCP, TCP_KEEPCNT,(void*)(&keepalive_probes),(socklen_t)sizeof(keepalive_probes)); |
设置SO_KEEPALIVE选项来开启KEEPALIVE,然后通过TCP_KEEPIDLE、TCP_KEEPINTVL和TCP_KEEPCNT设置keepalive的开始时间、间隔、次数等参数。
当然,也可以通过设置/proc/sys/net/ipv4/tcp_keepalive_time、tcp_keepalive_intvl和 tcp_keepalive_probes等内核参数来达到目的,但是这样的话,会影响所有的socket,因此建议使用setsockopt设置。
|
相关推荐
《TCP/IP网络编程》是尹圣雨先生的一本经典教程,专注于讲解如何使用C语言进行网络编程,特别是涉及TCP/IP协议栈的实现。这本教材深入浅出地介绍了网络编程的基础概念、技术以及实践方法,适合初学者和有一定经验的...
TCP/IP网络编程是计算机通信领域中的核心主题,它涉及到互联网上的数据传输协议栈。源码分析可以帮助我们深入理解这些协议的工作原理以及如何在实际应用中实现它们。以下是对标题和描述中涉及的知识点的详细解释: ...
对于IP编程,读者将接触到IP地址和端口号的使用,以及如何处理IP选项和头部字段。此外,书中的技巧可能涉及IP路由、IP分片与重组,以及IPV4和IPV6的转换。 此外,书中还可能涵盖UDP编程,尽管UDP不提供连接和可靠性...
基于TCP网络编程实现代码 ...基于TCP网络编程实现代码需要考虑的知识点包括套接字、服务器端实现、客户端实现、数据传输、错误处理、套接字选项、网络编程的security consideration、网络编程的性能优化等。
《Unix网络编程》和《TCP/IP详解》是网络编程领域中的两部权威著作,对于初学者和经验丰富的开发者来说,都是不可或缺的参考资料。这两本书详细地介绍了如何在Unix环境中进行网络编程,以及TCP/IP协议族的基本原理和...
3. **IP分片与重组**:了解IP数据报如何在不同MTU(最大传输单元)的网络中进行分片和重组,以及IP选项和首部校验。 4. **套接字编程**:掌握套接字API的使用,包括创建、绑定、监听、接受和连接等操作,以及如何...
TCP/IP Sockets编程是网络通信领域中的核心技术,尤其在C语言环境下,它的应用广泛且深入。本书《TCP/IP Sockets编程:C语言实现》第二版,以其通俗易懂的讲解方式,深受程序员们的喜爱,是学习网络编程的经典之作。...
《TCP+IP高效编程--改善网络程序的44个技巧》是一本专注于网络程序优化的指导书籍,主要针对TCP/IP协议栈的运用和C++编程语言进行深入探讨。该书通过对44个实用技巧的详细讲解,帮助开发者提升网络应用程序的性能、...
Java TCP/IP Socket编程是网络通信领域中的核心技术,广泛应用于服务器端和客户端之间的数据传输。本资源包含第二版书籍的相关源码,旨在帮助开发者深入理解并实践Socket编程。以下是关于Java TCP/IP Socket编程的...
在IT行业中,网络编程是构建分布式系统和网络应用的基础,而TCP/IP协议栈则是网络通信的核心。本主题聚焦于“基于VC的TCP/IP网络编程”,主要关注如何利用Microsoft Visual C++(VC)作为开发工具来实现TCP/IP协议的...
《高级TCP/IP编程》这本书是IT领域的经典之作,主要涵盖了网络通信的核心协议——TCP/IP的高级编程技术。这本书深入探讨了如何在Unix/Linux环境中利用C语言进行网络编程,旨在帮助开发者构建高效、可靠的网络应用...
Java TCP/IP Socket编程是网络通信领域中的核心技术,尤其在Java平台中,Socket是实现客户端与服务器之间通信的基础。原书第二版深入浅出地讲解了Java Socket编程的各个方面,为开发者提供了全面的学习资源。以下是...
Linux系统中的TCP/IP编程是网络通信的核心技术,它允许应用程序通过网络进行数据交换。本教程将深入探讨如何在Linux环境中构建TCP/IP通信程序,以及如何利用Linux提供的丰富的系统调用和函数来实现这一目标。 首先...
TCP/IP Socket网络编程是计算机通信领域中的核心技术,它允许不同设备通过网络进行数据交换。TCP/IP(Transmission Control Protocol/Internet Protocol)是互联网的基础协议,而Socket则是应用层与TCP/IP协议族通信...
W.Richard Stevens(1951-1999)是一位非常受人尊敬的专家,除了《TCP/IP详解》三卷本外,他还有其他两部最为畅销的作品:《UNIX环境高级编程》和《UNIX网络编程》(两卷本)。 目录 译者序 前言 第1章 概述 1 ...
IP层面,书中可能涉及了IP选项的使用和处理,如记录路由、时间戳等,这些在特定场景下可能有助于网络诊断和性能分析。此外,IP分片和重组策略的优化也是提高网络效率的一个方面。 对于网络程序的优化,还可能涉及到...
此外,书中对IP协议也进行了深入讨论,特别是IP分片与重组、IP选项以及IP多播等高级话题。IP分片用于解决不同网络设备MTU(最大传输单元)限制的问题,而IP多播则允许单个数据包被同时发送到多个目的地,常用于...
IP层的编程涉及IP地址、子网掩码、路由选择、ICMP(因特网控制消息协议)报文的发送和接收,以及IP选项的使用。还有可能讨论到多播编程,通过IP多播可以向多个目的地同时发送数据,节省网络资源。 网络编程中的一个...
Java TCP/IP Socket编程是Java网络编程中的重要组成部分,它提供了在网络间进行数据传输的基础机制。TCP(Transmission Control Protocol)和IP(Internet Protocol)是互联网上最基础的通信协议,而Socket则是TCP/...
本文将深入探讨"C++网络编程之TCP实例",涵盖TCP(传输控制协议)的基本概念、C++实现TCP服务器和客户端的关键步骤以及相关知识点。 TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议。它通过三次握手建立...