getsockopt()函数和setsockopt()函数

1.套接字创建以后,就可以利用它来传输数据, 但有时可能对套接字的工作方式有特殊要求,此时就需要修改套接字的属性; #include <sys/types.h> #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); 参数s为一个套接字,参数level是进行套接字选项操作的层次,可以取SOL_SOCKET(通用套接字),IPPROTO_IP(IP层套接字),IPPROTO_TCP(TCP层套接字)等值,一般取SOL_SOCKET来进行与特定协议不相关的操作,参数optname是套接字选项的名称,对于函数getsockopt, 参数optvai 用来存放获得的套接字选项, 参数optlen在调用前其值为optval指向的空间大小,调用完成后则其值为参数optval保存的结果的实际大小.对于函数setsockopt,参数optval是待设置的套接字选项的值,参数optlen 是该选项的长度. 这两个函数执行成功返回0,出错返回-1; 下面介绍SOL_SOCKET的选项.可以使用命令"man 7 socket"获得更详细的介绍;

  • SO_KEEPALIVE:如果没有设置SO_KEEPALIVE选项,那么即使TCP连接已经长时间没有数据传输时,系统也不会检测到这个连接是否还有效,对于服务器进程,如果某一客户端非正常断开连接,则服务器进程将一直被阻塞等待,因此服务器端程序要使用这个选项,如果某个客户端一端时间内没有反应则关闭该连接。
  • SO_RCVLOWAT和SO_SNDLOWAT SO_RCVLOWAT 表示接收缓冲区的下限,只有当接收缓冲区的数据超过了SO_RCVOWAT才会将数据传送到上层应用程序。SO_SNDLOWAT表示发送缓冲区的下限,只有当发送缓冲区中的数据超过了SO_SNDLOWAT才会将数据发送出去,linux 下这两个值都为1,不能被改变。也就是说,只要有数据的传送和接收就能通过函数getsockopt()函数获得,不能用setsockopt()函数更改。
  • SO_RCVTIMEO和 SO_SNDTIMEO可以设置对套接字读或写的超时时间:

struct   timeval{ long  tv_sec;                //秒数 long  tv_usec;               //微秒数 }; 成员tv_sec指定秒数,tv_usec指定微秒数,超时时间为这两个时间的和。

  • SO_BINDTODEVICE:将套接字绑定到特定的网络接口"eth0",此后只有该网络接口上的数据才会被套接字处理。如果将选项值设置为空字符或选项长度设为0将取消绑定。
  • SO_DEBUG:该选项只能对TCP套接字使用 ,设置了该选项后系统将保存TCP发送和接收的所有数据的相关信息,以便调试程序;
  • SO_REUSEADDR: linux系统中,如果一个socket 绑定一个端口,该socket正常关闭或程序异常退出后的一段时间内,该端口依然维持原来的绑定状态,其它程序无法绑定该端口,如果设置了该选项则可以避免这个问题,示例:

int   option_value = 1; int length = sizeof(option_value); setscokopt(sock_fd,SOL_SOCKET,SO_REUSEADDR,&option_value,length);

  • SO_TYPE

用于获取套接字的类型,如SOCK_DGRAM,SOCK_STREAM,SOCK_SEQPACKET,SOCK_RDM;该选项只能被getsockopt用来获取套接字类型,而不能使用函数setsockopt修改;

  • SO_ACCEPTCONN:该选项检测套接字是否处于监听状态 ,如果为0表示处于非监听状态,如果为1表示正在监听,该选项只能被函数getsockopt 用来获取监听状态信息。
  • SO_BROADCAST:该选项用来决定套接字是否能在网络上广播数据,实际应用要在网络上广播数据硬件必须支持广播数据(以太网支持广播)并且使用的是SOCK_DGRAM套接字,系统默认不支持广播,如果希望SOCK_DGRAM套接字支持广播,

int option_value = 1; setsockopt(sock_fd,SOL_SOCKET,SO_BROADCAST,&option_value,sizeof(int));

  • SO_SNDBUF和SO_RCVBUF:这两个用于设置套接字的发送和接收区的大小,对于TCP类型的套接字,缓冲区太小会影响TCP的流量控制,
  • SO_ERROR:获取套接字内部的错误变量 so_error,当套接字上发生了一步错误时,系统将设置套接字的so_error,异步错误是指错误的发生和错误被发现的时间不一致,通常是目的主机非正常关闭时发生这种错误。该选项只能被函数getsockopt用来获取so_error。

注意:调用完函数getsockopt 之后so_error的值被自动重新初始化。

2.多路复用select()

在客户端/服务器模型中,服务器端需要同时处理多个客户端的连接请求,此时就需要使用多路复用,实现多路复用最简单的方法是采用非阻塞方式套接字,服务器端不断查询各个套接字,如果有数据,则读出数据,如果没有则查看下一个套接字。 另一种方法是服务器进程并不主动询问套接字状态,而是向系统登记希望监视的套接字,然后阻塞,当套接字上有事件发生时 ,系统通知服务器进程告知哪个套接字上发生了什么事件,服务器进程查询对应的套接字,并进行处理,这就要用到函数select() #include <sys/select.h> #include <sys/time.h> #include <sys/types.h> #include <unistd.h> 函数原型:int select(int n,fd_set  *readfds,fd_set  *writefds, fd_set  *exceptfds,struct  timeval  *timeout); 参数n是需要监视的文件描述符数,要监听的文件描述符值为0~n-1,参数readfds指定需要监视可读文件描述符的集合 ,当这个集合中的一个描述符上有数据到达时,系统将通知 调用select函数的程序.参数writefds指定需要监视的可写文件描述符的集合,当这个集合的某个描述符可以发数据时, 程序将收到通知,参数exceptfds指定需要监视的异常文件描述符集合 ,当该集合中的一个描述符发生异常,程序会收到通知。参数timeout指定了阻塞的时间,如果在这个时间段的监视文件描述符上都没有时间发生,函数select()将返回,  这里的文件描述符既可以是普通文件的描述符,也可以是套接字描述符; 系统为文件描述符集合提供了一系列的宏以方便操作: FD_CLR(int fd,fd_set  *set);       //将文件描述符从集合set 中删除, FD_ISSET(int fd ,fd_set  *set)    //测试fd是否在set中 FD_SET(int  fd,fd_set  *set);            //在文件描述符集合中增加文件描述符fd; FD_ZERO(fd_set *set)           //清空set集合 来看个了例子

#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
void display_time(const char *string)
{
	int seconds;
	seconds = time((time_t *)NULL);
	printf("%s, %d\n",string,seconds);
}
int main(void)
{
	fd_set     readfds;
	struct timeval  timeout;
	int ret;
	/*监听文件描述符0是否有数据输入,文件描述符0表示标准输入*/
	FD_ZERO(&readfds);  //开始使用一个文件描述符集合前一般要将其清空
	FD_SET(0,&readfds);
	//设置阻塞的时间为10 秒
while(1)
{
	
	timeout.tv_sec = 10;
	timeout.tv_usec = 0;
	display_time("before select!");
	ret=select(1,&readfds,NULL,NULL,&timeout);
	display_time("after select");

     switch(ret)
    {
	case 0:
		printf("NO data in ten seconds!\n");
		exit(0);
		break;
	case -1:
		perror("select");
		exit(1);
		break;
	default:
		getchar();
		printf("Data is available now!\n");
   }
}	
	return 0;
}

结果:

yang@liu:~/syc/第11章$ ./a.out
before select!, 1438134782
1
after select, 1438134784
Data is available now!
before select!, 1438134784
after select, 1438134792
NO data in ten seconds!

程序执行时,等待几秒钟后按下任意键,从执行结果可以看出按下任意键后select立刻返回,又重新设置了select()监视键盘动作 ,可以发现,第二次只监听了8秒,好像时间是累积的,因为第一次用了2,秒,这是为什么呢,原来是系统会修改timeout的时间为剩余时间,所以应该把初始化时间放在循环内,每一次都进行初始化。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: getsockopt/setsockopt函数是用于设置和获取套接字选项的函数。其中,getsockopt用于获取指定套接字选项的值,而setsockopt用于设置指定套接字选项的值。这两个函数在网络编程中经常被用到。 ### 回答2: getsockoptsetsockopt函数是用来获取和设置套接字选项的API函数,在网络编程中十分常见。套接字选项是一个可选的参数,它允许用户设置套接字的某些属性,例如超时时间、是否启用广播、缓冲区大小等等。 getsockopt函数用于获取套接字选项的当前值。它需要传入以下参数: 1. sockfd: 套接字描述符; 2. level: 选项定义的协议层; 3. optname: 需要获取的选项名称; 4. optval: 指向一个缓冲区,用于存储获取到的选项值; 5. optlen: 缓冲区的大小。 setsockopt函数用于设置套接字选项的值。它需要传入以下参数: 1. sockfd: 套接字描述符; 2. level: 选项定义的协议层; 3. optname: 需要设置的选项名称; 4. optval: 指向一个缓冲区,用于存储需要设置的选项值; 5. optlen: 缓冲区的大小。 需要注意的是,不同的协议层和选项名称对应的值有所不同。可以通过man手册或者网络查找相关资料来获取更详细的信息。 这些函数在网络编程中经常被使用,例如可以通过setsockopt函数设置套接字的超时时间,当网络I/O操作超过指定时间时,会自动返回一个超时错误;也可以通过getsockopt函数来获取当前是否启用了广播选项等等。 总之,getsockoptsetsockopt函数可以让我们更方便地控制和监控套接字的行为,提高网络通信的效率和可靠性。 ### 回答3: getsockoptsetsockopt函数都是与网络编程相关的系统调用函数,它们用于控制和获取套接字选项。在进行网络编程时,我们需要使用这两个函数来调整套接字的设置,以便实现更好的网络通信效果。 具体地说,setsockopt函数可以设置某个套接字的选项值,例如设置套接字的发送和接收缓冲区大小、设置是否对数据包进行分片等等。而getsockopt函数则可以获取某个套接字的选项值,以便进行校验或者输出日志等功能。 关于参数方面,getsockoptsetsockopt函数都需要传入当前操作的套接字句柄,以及要设置或者获取的选项值。setsockopt函数还需要传入对应选项值的指针和大小;而getsockopt函数需要传入一个指向缓冲区的指针,用来接收获取的选项值和大小。 需要注意的是,每个选项都有对应的协议层级,而不同的选项可能只在特定协议的套接字上有效。因此,在使用这两个函数时,需要注意选项的协议层级,以及操作的套接字所使用的协议类型,避免出现无法设置或获取选项值的情况。 同时,getsockoptsetsockopt函数也有一定的返回值,setsockopt函数返回是否设置成功,而getsockopt函数返回获取的选项值的长度。在使用时,我们需要对返回值进行判断,以便及时发现并解决问题。 总之,getsockoptsetsockopt函数是网络编程中必不可少的函数。它们用于设置和获取套接字的选项值,以便我们能够更加精细地控制网络通信的行为,从而提高网络通信效率和质量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值