httpserver ---tcp参数设置

 

在对 socket 绑定和监听前经过了以下设置

  • 无阻塞(O_NONBLOCK
  • TCP 无延时(TCP_NODELAY
  • 可重用地址(SO_REUSEADDR

 对于 clien server需要设置:

  • 无阻塞
  • server -->无延时

 

1、SO_REUSEADDR选项:

在服务器程序中,SO_REUSEADDR socket选项通常在调用bind()之前被设置。
SO_REUSEADDR可以用在以下四种情况下: 
(摘自《Unix网络编程》卷一,即UNPv1)
1、当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时,而你启动的程序的socket2要占用该地址和端口,你的程序就要用到该选项。 

 2、SO_REUSEADDR选项允许在同一个端口上启动同一服务器的多个实例,只要每个实例捆绑一个不同的IP地址即可

 3、SO_REUSEADDR允许单个进程捆绑同一个端口到多个套接字上,只要每次捆绑指定不同的IP即可
 4、SO_REUSEADDR允许完全重复的捆绑:当一个IP地址和端口已绑定到某个套接字上,如果传输协议支持,同样的IP地址和端口还可已捆绑到另一个套接字上(一般本特性仅支持UDP)
        以下为使用SO_REUSEADDR建议:
           1、在所有TCP服务器中,在调用bind之前设置SO_REUSEADDR选项
           2、当编写一个可在同一时刻在同一主机上运行多次的多播应用程序时,设置SO_REUSEADDR选项,并将所参加多播组的地址作为本地IP地址捆绑

2、TCP_NODELAY

TCP_NODELAY和TCP_CORK基本上控制了包的“Nagle化”,Nagle化在这里的含义是采用Nagle算法把较小的包组装为更大的帧。TCP_NODELAY和TCP_CORK都禁掉了Nagle算法,只不过他们的行为不同而已。
TCP_NODELAY 不使用Nagle算法,不会将小包进行拼接成大包再进行发送,直接将小包发送出去,会使得小包时候用户体验非常好

3、SO_RCVBUF/SO_SNDBUF

SO_RCVBUF和SO_SNDBUF
        每个套接字都有一个发送缓冲区和一个接收缓冲区。对于TCP来说,套接字接收缓冲区中的可用空间的大小限制了TCP通告对端的窗口大小

4、SO_KEEPALIVE

SO_KEEPALIVE选项:
SO_KEEPALIVE/TCP_KEEPCNT/TCP_KEEPIDLE/TCP_KEEPINTVL
        如果一方已经关闭或异常终止连接,而另一方却不知道,我们将这样的TCP连接称为半打开的。

        TCP通过保活定时器(KeepAlive)来检测半打开连接。
         在高并发的网络服务器中,经常会出现漏掉socket的情况,对应的结果有一种情况就是出现大量的CLOSE_WAIT状态的连接。这个时候,可以通过设置KEEPALIVE选项来解决这个问题,

5、SO_REUSEPORT

SO_REUSEPORT支持多个进程或者线程绑定到同一端口,提高服务器程序的性能,解决的问题:

  • 允许多个套接字 bind()/listen() 同一个TCP/UDP端口
    • 每一个线程拥有自己的服务器套接字
    • 在服务器套接字上没有了锁的竞争
  • 内核层面实现负载均衡
  • 安全层面,监听同一个端口的套接字只能位于同一个用户下面

其核心的实现主要有三点:

  • 扩展 socket option,增加 SO_REUSEPORT 选项,用来设置 reuseport。
  • 修改 bind 系统调用实现,以便支持可以绑定到相同的 IP 和端口
  • 修改处理新建连接的实现,查找 listener 的时候,能够支持在监听相同 IP 和端口的多个 sock 之间均衡选择。

6、TCP_DEFER_ACCEPT选项:

TCP_DEFER_ACCEPT
defer accept,从字面上理解是推迟accept,实际上是当接收到第一个数据之后,才会创建连接,三次握手完成,连接还没有建立。

对于像HTTP等非交互式的服务器,这个很有意义,可以用来防御空连接攻击(只是建立连接,但是不发送任何数据)。
使用方法如下:

7、TCP_KEEPIDLE TCP_KEEPINTVL

 设置SO_KEEPALIVE选项来开启KEEPALIVE,然后通过TCP_KEEPIDLE、TCP_KEEPINTVL和TCP_KEEPCNT设置keepalive的开始时间、间隔、次数等参数

 

 

9、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()不被阻塞立即执行,当close某个连接的时候TCP将会中止该连接。这就是说TCP将丢弃保存在套接字发送缓冲区的任何数据,并发送一个RST给对端,而没有通常的四分组终止连接序列。这么一来就避免了TCP的TIME_WAIT状态,然而存在以下可能性:在2MSL秒内创建该连接的另一个化身,导致来自刚被终止的连接上的旧的重复分节被不正确的递送到新的化身上。(TIME_WAIT状态存在的理由后就很好理解)

    这种关闭方式称为“强制”或“失效”关闭。
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).

10、SO_TIMEOUT

通过这个选项来设置读取数据超时

 


 

tw_recyle:https://blog.csdn.net/yunhua_lee/article/details/8146845

posted @ 2020-03-29 23:01  codestacklinuxer  阅读(376)  评论(0编辑  收藏  举报