锐英源软件
第一信赖

精通

英语

开源

擅长

开发

培训

胸怀四海 

第一信赖

当前位置:锐英源 / 在线教育 / SOCKET网络通信开发公开课 / Sockets-Options Socket选项
服务方向
人工智能数据处理
人工智能培训
kaldi数据准备
小语种语音识别
语音识别标注
语音识别系统
语音识别转文字
kaldi开发技术服务
软件开发
运动控制卡上位机
机械加工软件
软件开发培训
Java 安卓移动开发
VC++
C#软件
汇编和破解
驱动开发
联系方式
固话:0371-63888850
手机:138-0381-0136
Q Q:396806883
微信:ryysoft

3.21 Sockets-Options Socket选项


要点:

  • fcntl()
  • ioctl()
  • getsockopt()和setsockopt()

3.21.1 获取和设置Socket选项

  • 有几种方法都可以用来获取和设置Socket的选项。
  • 常用的形式是getsockopt()函数和setsockopt()函数。
  • 也可用fcntl()(文件控制函数)和ioctl()(输入/输出控制)函数
  • 对于特殊的包的发送和接收,可以使用flag参数来控制。send或recv里的flag参数。

3.21.2 fcntl()

  • fcntl()函数用来控制一系列的描述符,这里我们只关心socket的用法
  • fcntl()修改方法也有很多:

#include <unistd.h>

#include <fnctl.h>

int fcntl(int sd,int cmd);

int fcntl(int sd,int cmd,long arg);

  • fcntl()修改依赖于cmd:

F_GETFL:读取描述符对应的所有标志,写入到返回值里。

F_SETFL:设置文件描述符的标志,设置值为arg;

F_GETOWN:查找这个socket属于哪个进程,也就是哪个进程接收SIGIO和SIGURG。进程号写入到返回值里。

F_SETOWN:设置隶属的进程。

F_GETSIG:查找出来当能运行I/O操作时发送的信号

F_SETSIG:设置当I/O操作能运行时发送的信号。0值代表SIGIO。返回值是发送的信号,如果是SIGIO,则是0。

  • 对于socket,能够进行的设置是:
    • O_NONBLOCK:设置socket为非阻塞模式
    • O_ASYNC:在输入或输出操作能运行时,发送SIGIO信号。注意,实际发送的信号能够修改。这个标志不是在所有操作系统上都有效。
  • 在使用fcntl()函数时,常见的错误是没有保留未修改标志。下面的例子就没有问题:

flags=fcntl(sd,F_GETFL,0);
fcntl(sd,F_SETFL,flags | O_NONBLOCK);

  • 当带外数据接收到时,SIGURG信号会发送出来。(这会导致select()函数报告一个异常条件.)F_GETSIG是Linux才有的动作。
  • 当socket创建时,它考虑没有隶属进程。当从监听socket创建出来新socket时,此新socket的隶属进程从监听socket里继承过来。

3.21.3 ioctl()函数

  • ioctl()函数几乎能用于所有硬件设备和很多内核模块,来检查和设置行为。
  • 原型如下:

#include <sys/ioctl.h>
int ioctl(int sd,int command,char*argp);
第三个参数是可选的,依赖于第二个参数。

  • 和socket相关的命令有:

命令

含意

SIOCGSTAMP

从socket里会传递包给用户,传递会发生在具体时刻上,这个命令把最后的时刻返回到第三个参数里,类型为struct timeval

SIOCSPGRP

设置接收SIGIO和SIGURG信号的进程(进程组);这种情况下,第三个参数指向一个进程ID。这和fcntl()调用F_SETOWN命令效果一样。

FIOASYNC

重置O_ASYNC标志;第三个参数是标志值。这和fcntl()调用F_SETFL和O_ASYNC效果一样。

SIOCGPGRP

获取接收信号的当前进程(或组)。这和使用fcntl()调用F_GETOWN类似。

  • 注意:最后三个是fcntl()的功能复制,就Posix规则关注点上来讲,fcntl()推荐,ioctl()不赞成使命。然而,ioctl()在实际情况里还是有可能出现。
  • 更多命令请参考man 7 socket来学习。

3.21.4 getsockopt()和setsockopt()函数

  • 为了检查和修改socket的属性,使用下面函数:

#include <sys/types.h>
#include <sys/socket.h>
int getsockopt(int sd,int level,int optname,void *optval,socklen_t *optlen);
int setsockopt(int sd,int level,int optname,const void *optval,socklen_t optlen);

  • 第一个参数sd必须是有效的描述符。
  • level参数指示操作对应的常用选项类型。SOL_SOCKET对应socket层,IPPROTO_IP对应IPV4层,等等。
  • 检查和设置对应的选项由optname参数指定,同时optval指向的缓冲里要么包含设置值,要么包含返回的检查结果值。在检查值时,缓冲的长度返回到最后一个参数里,在设置时,最后一个参数表示了长度。(注意,在setsockopt里最后一个参数不是指针)。
  • 对于大多数socket级别的optval,要么是整数值,要么是布尔值。记住,我们允许socket能够立即重用,通过调用下面的代码来实现:(这里重用是指关闭带有监听状态进程后,再次打开进程,能够bind上)。

int yes=1;
setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes));
上面是一个非常好的示例。

  • socket级别的选项通过帮助man 7 socket可以查到,他们有:

类型

含意

SO_KEEPALIVE

int

定期检查看连接是否有效

SO_OOBINLIN

int

带外数据会被遗弃

SO_RCVLOWAT
SO_SNDLOWAT

int

发送和接收缓冲警戒线。在数据发送给协议或用户前,在缓冲里的最小字节个数

SO_BSDCOMAT

 

 

SO_PASSCRED

int

 

SO_PEERCRED

struct
ucred

 

SO_BINDTODEVICE

char*

绑定socket到一个指定设备上(比如eth0)。传递空值用来释放。(适用于多个网卡情况)

SO_DEBUG

int

允许调试跟踪。只适用于超级用户

SO_REUSEADDR

int

允许重用本地地址

SO_TYPE

int

获取socket类型

SO_DONTROUTE

int

忽略路由表;适用于直接连接的主机(在一个局域网里)

SO_BROADCAST

int

允许接收或发送组播包。

SO_SNDBUF

int

获取或设置发送缓冲长度的最大值。参考/proc/sys/net/core/wmem.default和/proc/sys/net/core/wmem.max.

SO_RCVBUF

int

获取或设置接收缓冲长度的最大值。参考/proc/sys/net/core/rmem.default和/proc/sys/net/core/rmem.max.

SO_LINGER

struct
linger

当允许时,延迟关闭socket,直到缓冲队列里的数据处理完了或超时时间到了,才关闭。结构里有超时时间

SO_PRIORITY

int

设置socket里所有包的级别

SO_ERROR

int

获取且清除未决socket错误

友情链接
版权所有 Copyright(c)2004-2021 锐英源软件
公司注册号:410105000449586 豫ICP备08007559号 最佳分辨率 1024*768
地址:郑州市金水区郑州大学北校区院(文化路97号院)内