Socket选项的那些事(一)

Socket选项的那些事(一)

今天跟大家分享套接字选项的一些事情,以下就是要详细介绍的东西,通过实际的编程来分享这些东西,有什么问题或者错误欢迎来讨论哈!!!!!

  • SOL_SOCKET协议族选项(通用地址族选项)
  • IPPROTO_ TCP和IPPROTO_ IP选项
  • ioctl()函数

OK,进入我们今天的分享,先来讲述SOL_SOCKET协议族选项(通用地址族选项)

获取和设置套接字选项

其实在进行网络编程的时候,我们需要经常去查看并且设置套接字的某些特性。例如我们想去设置地址复用,设置读写数据的超时时间,想对读写缓冲区的大小进行调整,其中获得套接字的选项就是getsckopt()函数,那么对应话设置套接字的选项就是sesockopt()函数

介绍一下它们两个

#include<sys/socket.h>

int getsockopt(int s,int level,int optname,void* optval.socklen_t* optlen);
int setsockopt(int s,int level,int optname,void* optval.socklen_t optlen);

用来获取和设置某个套接字相关的选项,选项可能存在于多层协议中,他们总会出现在最上面的套接字层。当对套接字选项进行操作的时候,我们必须给出选项所在的层次与名称,为了操作套接字层的选项,应该将层的值指定为SOL_SOCKET,为了控制其它层的选项,必须给出控制选项的协议类型号。

我们来介绍上面两个函数参数的含义

  • s:表示将要获取和设置的套接字描述符
  • level:表示层次
  • optname:表示选项名
  • optval:表示操作的内存缓冲区
  • optlen:表示optval的长度

对于getsockopt,指向用于获取返回值的缓冲区,setsockopt指向设置参数的缓冲区。optval表示第optval的长度。getsockopt,指向socklen_t类型的指针,当用于传入参数时,表示传入optval的实际长度。当用于传出参数时,表示用于保存optval的最大长度。

当用于传出参数时,表示用于保存optval的最大长度。对于setopt函数,optlen表示第四个参数实际的长度,在函数执行成功的时候返回值为0,函数执行失败时返回为-1。同时我们可以根据错误代码来判断错误类型。

getsockopt()函数和setsocktopt()函数错误的代码含义:

  • EBADF:参数s不是有效的文件描述符
  • EFAULT:optval指向的内存并非有效的进程空间
  • EINVAL:在调用setsockopt()函数时,optlen无效
  • ENOPROTOOPT:指定的协议层不能识别选项
  • ENOTSOCK:s描述的不是套接字的描述符

按照参数level值的不同,套接字选项可以分为三大类:

  • 通用套接选项:level的值为SOL_SOCKET
  • IP选项:level的值为IPPROTO_IP
  • TCP选项:level的值为IPPROTO_TCP

SO_KEEPALIVE选项

SO_KEEPALIVE保持连接选项,2小时没有数据交互,发送探测报文,有三种回应:

  • 回应一个ACK报文
  • 回应一个RST报文
  • 没有回任何回应

使用方法:

就是调用setsockopt进行设置

int optval =1; 
setsockopt(sockfd,SOL_SOCKET,SO_KEEPALIVE,&optval,sizeof(optval));

第二个参数表示通用地址族选项,第三个就表示KEEPALIVE选项

SO_LINGER选项

SO_LINGER缓冲区处理方式选项,主要用于设置TCP连接关闭时的行为方式,它的操作通过一个结构体进行:

struct linger{
int l_onoff; //  开启(非0)关闭(0
int l_linger; //停留时间
};

根据以上结构体的不同,close调用可能产三种行为

我们介绍一下产生三种行为的不同方式:

  • l_ onoff等于0,此时SO_ LINGER不起作用,close用默认行为来关闭套接字
  • l_ onoff不为0,l_ linger为0,close系统调用立即返回,TCP将丢弃发送缓冲区中的残留数据,同时给对方发送一个复位报文段
  • l_ onoff不为0,l_ linger不为0,那么这个时候close的行为取决于两个条件,第一个条件是被关闭的套接字中的发送缓冲区中是否还有残留的数据,第二个条件就是该套接字是阻塞的还是飞阻塞的。对于阻塞的来说close将等待。如果是非阻塞的将会立即返回。

使用方法:

optval.l_onoff =1;
optval.l_linger =60; 
setsockopt(sockfd,SOL_SOCKET,SO_LINGER,&optval,sizeof(optval));

设置两个参数,然后进行set设置即可。

SO_ RECVBUF和SO_ SNDBUF选型

用于操作发送缓冲区和接收缓冲区的大小,使用的时候我们需要注意两点。

  • 设置TCP/UDP连接的接收/发送缓冲区的含义:在UDP连接中他是无连接,发送缓冲区在数据通过网络发送后就可以丢弃不用保存,而接收缓冲区就需要保存数据,直到客户端进行读取,由于UDP没有流量控制,当缓冲区过小时发送端局部时间内会产生爆发性数据传输,因此在使用UDP时,需要将接收缓冲区设置为比较大的值。而在TCP连接中,接收缓冲区的大小,就是滑动窗口的大小,TCP的接收缓冲区不可能溢出,因为它不允许对方发送超过缓冲区大小的数据
  • 在connect()函数调用之前设置:因为接收缓冲区的大小与滑动窗口的大小是一致的,而滑动窗口的协商是在建立连接的时候通过同步报文获得的。对于客户端来说,接收缓冲区的大小要在connnect系统调用前进行设置,因为connect需要通过同步报文段建立连接,而对于服务器来说,需要在listen之前进行接收缓冲区的大小设置。因为accept函数的返回值是继承了listen描述符属性

SO_ RCVLOWAT和SO_ SNDLOWAT选选型

SO_ RCVLOWAT表示接收超时,SO_ SNDLOWAT表示发送超时,设置是通过一个结构体实现的。

struct  timeval{
   time_t tv_sec;
   sseconds_t tv_usec;
};

SO_ RCVTIMEO和SO_ SNDTIMEO选项

SO_ RCVTIMEO和SO_ SNDTIMEO选项表示TCP接收缓冲区和发送缓冲区的低水位标记,它们一般会被I/O系统复用调用,来判断socket是否可读或者可写。

SO_REUSEADDR选项

表示可以重复使用本地地址和端口吗,这个设置在服务器端经常被使用。设置了SO_ REUSEADDR地址可重用选项,设置此选项可以使用被处于TIME_WAIT状态的连接占用的socket地址:

比如说某个服务器进程占用了TCP服务器的80端口。当再次监听的时候会返回错误。设置了此选项可以解决这个问题。也就是可以共用这个端口。有的时候,我们经常会遇到,当我们非正常退出的时候,这个端口会过一段时间内核才会释放,或者很久都没有被释放,我们无法再次开启服务器,设置了此选项就可以很好的解决这个问题了。

此选项的实际编程演示:

int sock = socket(AF_INET,SOCK_STREAM,0);
assert(sock >=0);
int reuse = 1;

//设置SO_REUSEADDR可复用选项
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse));


//服务器的长用结构设置
struct sockaddr_in address;
bzero(&address,sizeof(address));
address.sin_family = AF_INET;
inet_pton(AF_INET,ip,&address.sin_addr);
address.sin_port = htons(port);
int ret = bind(sock,(struct sockaddr*)&address,sizeof(address));

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章