网络编程学习_套接字选项

本文是UNP第7章学习笔记

一,getsockopt和setsockopt函数

#include <sys/socket.h>

int getsockopt(int sockfd, int level, int optname, void* optval socklen_t* optlen);

int setsockopt(int sockfd, int level, int optname, const void* optval, socklen_t optlen);

参数:

  1. sockfd: 套接字fd
  2. level: 如果是通用为SOL_SOCKET,如果是TCP专用,是IPPROT_TCP,当然其他协议也有专门的level值
  3. optname, 选项名
  4. optval: 选项值
  5. optlen: optval的长度
返回: 成功:0  失败:-1

二,SO_RCVBUF和SO_SNDBUF
这是两个socket通用选项(即level=SOL_SOCKET),用来设置发送和接受缓冲区的大小. 常见的是设置成65535,好像可以在一定条件下提高性能(好吧原理我不懂)
注意一个连接的SO_RCVBUF是在连接建立的时候就确定了的,所以如果需要修改的话,需要在connect或listen之前设置

三,SO_REUSEADDR
这是最常设置的选项,没有之一. 所有TCP服务器都应该在bind之前设置这个选项
其作用是当accept的连接还存活的时候,如果listenfd断掉的话可以重启.(如果不设置会因为端口已被占用而bind失败)
注意开启了这个选项bind也会返回-1, 但可以正常工作
注: 如果是一个普通的练手小程序,这个选项不设置也无所谓(通常listenfd不会被关闭,关了也不会重启),但对于健壮的高并发服务器来说这个选项是必要的.

四, fcntl函数, 设置非阻塞
fcntl 意思是 file control, 这个函数常用于将socket设置成非阻塞模式
#include <fcntl.h>
int fcntl(int fd,int cmd, .../*int arg*/);
参数:
  1. fd:不解释
  2. cmd: 一般为F_SETFL 或 F_GETFL
  3. arg: 设置非阻塞时添 O_NONBLOCK
注意给socket设置flag之前需要先获取flag然后求或,不能直接设置, 常见代码如下(省略了错误处理)
int flag=fcntl(fd,F_GETFL,0);
flag |= O_NONBLOCK;
fcntl(fd,F_SETFL,flag);

五,SO_LINGER选项
这个选项可以通过改变close的行为(直接发送RST)从而避免TIME_WAIT状态.
struct linger opt;
opt.l_onoff=1;
opt.l_linger=0;
setsockopt(fd,SOL_SOCKET,SO_LINGER,&opt,sizeof(opt));
 一般来说TIME_WAIT是有一定用处的,不需要刻意避免,但存在需要避免的情况,例如一个客户端需要建立大量的短连接与服务器进行通信. 这时如果不避免TIME_WAIT就会导致端口被占满. 另一种避免TIME_WAIT的方法是修改内核参数,但会影响所有进程. 以下方法copy自网络,不过亲测可用.

如发现系统存在大量TIME_WAIT状态的连接,通过调整内核参数解决,
vim /etc/sysctl.conf
编辑文件,加入以下内容:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
然后执行 /sbin/sysctl -p 让参数生效。

net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
net.ipv4.tcp_fin_timeout 修改系统默认的 TIMEOUT 时间


你可能感兴趣的:(网络编程学习_套接字选项)