当前位置: 技术问答>linux和unix
一直不知道IP数据报的选项字段怎么用,请指教
来源: 互联网 发布时间:2015-09-11
本文导语: 小弟驽钝,始终没看明白IP数据报的选项字段在编程时怎么设置。 填写数据报时怎么处理选项? 我想写一个有记录路由功能的ping程序,可是就是不知道该怎样设置选项,另外该怎样读出选项后的数据 请各位指教,...
小弟驽钝,始终没看明白IP数据报的选项字段在编程时怎么设置。
填写数据报时怎么处理选项?
我想写一个有记录路由功能的ping程序,可是就是不知道该怎样设置选项,另外该怎样读出选项后的数据
请各位指教,最好能给些源代码,文字资料我实在看不明白了
多谢
如果谁有ping 程序的完整代码,请发我信箱: shaoyan@pact518.hit.edu.cn
填写数据报时怎么处理选项?
我想写一个有记录路由功能的ping程序,可是就是不知道该怎样设置选项,另外该怎样读出选项后的数据
请各位指教,最好能给些源代码,文字资料我实在看不明白了
多谢
如果谁有ping 程序的完整代码,请发我信箱: shaoyan@pact518.hit.edu.cn
|
获得或改变socket 属性
int getsockopt(int sockfd, int level, int name, char *value, int *optlen);
int setsockopt(int sockfd, int level, int name, char *value, int *optlen);
level:(级别): 指定选项代码的类型。
SOL_SOCKET: 基本套接口
IPPROTO_IP: IPv4 套接口
IPPROTO_IPV6: IPv6 套接口
IPPROTO_TCP: TCP 套接口
level 一般为常数SOL_SOCKET
name 选项名称
value 选项值:是一个指向变量的指针,变量可以是整形,套接口结构, 其他结构类
型:linger{}, timeval{ }
optlen optval 的大小
常用选项的有:
[SOL_SOCKET]
SO_BROADCAST 允许发送广播数据 int
适用於 UDP socket。其意义是允许 UDP socket 「广播」(broadcast)讯息到网路上。
SO_DEBUG 允许调试 int
SO_DONTROUTE 不查找路由 int
SO_ERROR 获得套接字错误 int
SO_KEEPALIVE 保持连接 int
检测对方主机是否崩溃,避免(服务器)永远阻塞于TCP 连接的输入。 设置该选项后,如果2
小时内在此套接口的任一方向都没有数据交换,TCP 就自动给对方 发一个保持存活探测分节
(keepalive probe)。这是一个对方必须响应的TCP 分节.它会导致以下三种情况: 对方接收
一切正常:以期望的ACK 响应。2 小时后,TCP 将发出另一个探测分节。 对方已崩溃且已重
新启动:以RST 响应。套接口的待处理错误被置为ECONNRESET,套接 口本身则被关闭。 对
方无任何响应:源自berkeley 的TCP 发送另外8 个探测分节,相隔75 秒一个,试图得到 一
个响应。在发出第一个探测分节11 分钟15 秒后若仍无响应就放弃。套接口的待处理错 误被
置为ETIMEOUT,套接口本身则被关闭。如ICMP 错误是“host unreachable(主机不 可达)”,
说明对方主机并没有崩溃,但是不可达,这种情况下待处理错误被置为 EHOSTUNREACH。
SO_DONTLINGER 若为真,则SO_LINGER 选项被禁止。
SO_LINGER 延迟关闭连接 struct linger
上面这两个选项影响close 行为
选项 间隔 关闭方式 等待关闭与否
SO_DONTLINGER 不关心 优雅 否
SO_LINGER 零 强制 否
SO_LINGER 非零 优雅 是
若设置了SO_LINGER(亦即linger 结构中的l_onoff 域设为非零,参见2.4,4.1.7 和4.1.21
各节),并设置了零超时间隔,则closesocket()不被阻塞立即执行,不论是否有排队数据未发
送或未被确认。这种关闭方式称为“强制”或“失效”关闭,因为套接口的虚电路立即被复位,且丢
失了未发送的数据。在远端的recv()调用将以WSAECONNRESET 出错。
若设置了SO_LINGER 并确定了非零的超时间隔,则closesocket()调用阻塞进程,直到所剩
数据发送完毕或超时。这种关闭称为“优雅的”关闭。请注意如果套接口置为非阻塞且
SO_LINGER 设为非零超时,则closesocket()调用将以WSAEWOULDBLOCK 错误返回。
若在一个流类套接口上设置了SO_DONTLINGER(也就是说将linger 结构的l_onoff 域设为
零;参见2.4,4.1.7,4.1.21 节),则closesocket()调用立即返回。但是,如果可能,排队
的数据将在套接口关闭前发送。
SO_OOBINLINE 带外数据放入正常数据流,在普通数据流中接收带外数据 int
SO_RCVBUF 接收缓冲区大小 int
设置接收缓冲区的保留大小
与 SO_MAX_MSG_SIZE 或TCP 滑动窗口无关,如果一般发送的包很大很频繁,那么使用这
个选项
SO_SNDBUF 发送缓冲区大小 int
设置发送缓冲区的保留大小
与 SO_MAX_MSG_SIZE 或TCP 滑动窗口无关,如果一般发送的包很大很频繁,那么使用这
个选项
每个套接口都有一个发送缓冲区和一个接收缓冲区。 接收缓冲区被TCP 和UDP 用来将接收到
的数据一直保存到由应用进程来读。 TCP:TCP 通告另一端的窗口大小。 TCP 套接口接收缓
冲区不可能溢出,因为对方不允许发出超过所通告窗口大小的数据。 这就是TCP 的流量控制,
如果对方无视窗口大小而发出了超过宙口大小的数据,则接 收方TCP 将丢弃它。 UDP:当接
收到的数据报装不进套接口接收缓冲区时,此数据报就被丢弃。UDP 是没有 流量控制的;快的
发送者可以很容易地就淹没慢的接收者,导致接收方的UDP 丢弃数据报。
SO_RCVLOWAT 接收缓冲区下限 int
SO_SNDLOWAT 发送缓冲区下限 int
每个套接口都有一个接收低潮限度和一个发送低潮限度。它们是函数selectt 使用的, 接收低
潮限度是让select 返回“可读”而在套接口接收缓冲区中必须有的数据总量。 ——对于一个TCP
或UDP 套接口,此值缺省为1。发送低潮限度是让select 返回“可写” 而在套接口发送缓冲区
中必须有的可用空间。对于TCP 套接口,此值常缺省为2048。 对于UDP 使用低潮限度, 由
于其发送缓冲区中可用空间的字节数是从不变化的,只要 UDP 套接口发送缓冲区大小大于套接
口的低潮限度,这样的UDP 套接口就总是可写的。 UDP 没有发送缓冲区,只有发送缓冲区的
大小。
SO_RCVTIMEO 接收超时 struct timeval
SO_SNDTIMEO 发送超时 struct timeval
SO_BROADCAST:获得或设置socket 状况,使之可以广播发送数据报。(只能用于UDP 方式)。
SO_REUSEADDR:设置该socket 绑定的端口可以被重用。
注意:在Linux 系统中,如果一个socket 绑定了某个端口,该socket 正常关闭或程序退出后,
在一段时间内该端口依然保持被绑定的状态,其他程序(或者重新启动的原程序)无法绑定该端
口。可以通过调用以下语句避免该问题:
opt = 1;
len = sizeof(opt);
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,&len);
SO_EXCLUSIVEADDRUSE
独占模式使用端口,就是不充许和其它程序使用SO_REUSEADDR 共享的使用某一端口。
在确定多重绑定使用谁的时候,根据一条原则是谁的指定最明确则将包递交给谁,而且没有权限
之分,也就是说低级权限的用户是可以重绑定在高级权限如服务启动的端口上的,这是非常重大
的一个安全隐患,
如果不想让自己程序被监听,那么使用这个选
int getsockopt(int sockfd, int level, int name, char *value, int *optlen);
int setsockopt(int sockfd, int level, int name, char *value, int *optlen);
level:(级别): 指定选项代码的类型。
SOL_SOCKET: 基本套接口
IPPROTO_IP: IPv4 套接口
IPPROTO_IPV6: IPv6 套接口
IPPROTO_TCP: TCP 套接口
level 一般为常数SOL_SOCKET
name 选项名称
value 选项值:是一个指向变量的指针,变量可以是整形,套接口结构, 其他结构类
型:linger{}, timeval{ }
optlen optval 的大小
常用选项的有:
[SOL_SOCKET]
SO_BROADCAST 允许发送广播数据 int
适用於 UDP socket。其意义是允许 UDP socket 「广播」(broadcast)讯息到网路上。
SO_DEBUG 允许调试 int
SO_DONTROUTE 不查找路由 int
SO_ERROR 获得套接字错误 int
SO_KEEPALIVE 保持连接 int
检测对方主机是否崩溃,避免(服务器)永远阻塞于TCP 连接的输入。 设置该选项后,如果2
小时内在此套接口的任一方向都没有数据交换,TCP 就自动给对方 发一个保持存活探测分节
(keepalive probe)。这是一个对方必须响应的TCP 分节.它会导致以下三种情况: 对方接收
一切正常:以期望的ACK 响应。2 小时后,TCP 将发出另一个探测分节。 对方已崩溃且已重
新启动:以RST 响应。套接口的待处理错误被置为ECONNRESET,套接 口本身则被关闭。 对
方无任何响应:源自berkeley 的TCP 发送另外8 个探测分节,相隔75 秒一个,试图得到 一
个响应。在发出第一个探测分节11 分钟15 秒后若仍无响应就放弃。套接口的待处理错 误被
置为ETIMEOUT,套接口本身则被关闭。如ICMP 错误是“host unreachable(主机不 可达)”,
说明对方主机并没有崩溃,但是不可达,这种情况下待处理错误被置为 EHOSTUNREACH。
SO_DONTLINGER 若为真,则SO_LINGER 选项被禁止。
SO_LINGER 延迟关闭连接 struct linger
上面这两个选项影响close 行为
选项 间隔 关闭方式 等待关闭与否
SO_DONTLINGER 不关心 优雅 否
SO_LINGER 零 强制 否
SO_LINGER 非零 优雅 是
若设置了SO_LINGER(亦即linger 结构中的l_onoff 域设为非零,参见2.4,4.1.7 和4.1.21
各节),并设置了零超时间隔,则closesocket()不被阻塞立即执行,不论是否有排队数据未发
送或未被确认。这种关闭方式称为“强制”或“失效”关闭,因为套接口的虚电路立即被复位,且丢
失了未发送的数据。在远端的recv()调用将以WSAECONNRESET 出错。
若设置了SO_LINGER 并确定了非零的超时间隔,则closesocket()调用阻塞进程,直到所剩
数据发送完毕或超时。这种关闭称为“优雅的”关闭。请注意如果套接口置为非阻塞且
SO_LINGER 设为非零超时,则closesocket()调用将以WSAEWOULDBLOCK 错误返回。
若在一个流类套接口上设置了SO_DONTLINGER(也就是说将linger 结构的l_onoff 域设为
零;参见2.4,4.1.7,4.1.21 节),则closesocket()调用立即返回。但是,如果可能,排队
的数据将在套接口关闭前发送。
SO_OOBINLINE 带外数据放入正常数据流,在普通数据流中接收带外数据 int
SO_RCVBUF 接收缓冲区大小 int
设置接收缓冲区的保留大小
与 SO_MAX_MSG_SIZE 或TCP 滑动窗口无关,如果一般发送的包很大很频繁,那么使用这
个选项
SO_SNDBUF 发送缓冲区大小 int
设置发送缓冲区的保留大小
与 SO_MAX_MSG_SIZE 或TCP 滑动窗口无关,如果一般发送的包很大很频繁,那么使用这
个选项
每个套接口都有一个发送缓冲区和一个接收缓冲区。 接收缓冲区被TCP 和UDP 用来将接收到
的数据一直保存到由应用进程来读。 TCP:TCP 通告另一端的窗口大小。 TCP 套接口接收缓
冲区不可能溢出,因为对方不允许发出超过所通告窗口大小的数据。 这就是TCP 的流量控制,
如果对方无视窗口大小而发出了超过宙口大小的数据,则接 收方TCP 将丢弃它。 UDP:当接
收到的数据报装不进套接口接收缓冲区时,此数据报就被丢弃。UDP 是没有 流量控制的;快的
发送者可以很容易地就淹没慢的接收者,导致接收方的UDP 丢弃数据报。
SO_RCVLOWAT 接收缓冲区下限 int
SO_SNDLOWAT 发送缓冲区下限 int
每个套接口都有一个接收低潮限度和一个发送低潮限度。它们是函数selectt 使用的, 接收低
潮限度是让select 返回“可读”而在套接口接收缓冲区中必须有的数据总量。 ——对于一个TCP
或UDP 套接口,此值缺省为1。发送低潮限度是让select 返回“可写” 而在套接口发送缓冲区
中必须有的可用空间。对于TCP 套接口,此值常缺省为2048。 对于UDP 使用低潮限度, 由
于其发送缓冲区中可用空间的字节数是从不变化的,只要 UDP 套接口发送缓冲区大小大于套接
口的低潮限度,这样的UDP 套接口就总是可写的。 UDP 没有发送缓冲区,只有发送缓冲区的
大小。
SO_RCVTIMEO 接收超时 struct timeval
SO_SNDTIMEO 发送超时 struct timeval
SO_BROADCAST:获得或设置socket 状况,使之可以广播发送数据报。(只能用于UDP 方式)。
SO_REUSEADDR:设置该socket 绑定的端口可以被重用。
注意:在Linux 系统中,如果一个socket 绑定了某个端口,该socket 正常关闭或程序退出后,
在一段时间内该端口依然保持被绑定的状态,其他程序(或者重新启动的原程序)无法绑定该端
口。可以通过调用以下语句避免该问题:
opt = 1;
len = sizeof(opt);
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,&len);
SO_EXCLUSIVEADDRUSE
独占模式使用端口,就是不充许和其它程序使用SO_REUSEADDR 共享的使用某一端口。
在确定多重绑定使用谁的时候,根据一条原则是谁的指定最明确则将包递交给谁,而且没有权限
之分,也就是说低级权限的用户是可以重绑定在高级权限如服务启动的端口上的,这是非常重大
的一个安全隐患,
如果不想让自己程序被监听,那么使用这个选