Alex's Blog
===========================================================
===========================================================

from

前段时间,一个朋友发来邮件,说在RedHat Linux 9.0 操作系统的机器上,编写了一个服务程序。该服务程序用Ctrl+C终止后,不能够马上重新运行。出现地址绑定错误,也就是调用bind()函数时,出现错 误。但过了几分钟后,即可以正常运行。不明白原因,并希望能给于解决。
首先,来了解出现这个问题的原因。如果出现上面的情况,可以用netstat -an 命令查看一下,就会发现那个服务程序所使用的端口处在CLOSE_WAIT状态。当程序执行主动关闭的时候,就会进入这种状态。还有一种情况,就是客户端 还在保持连接,但服务器却意外终止,这种情况,也会有这种状态产生,特别是在一些老的UNIX操作系统中,非常常见。例如SCO系统。那么这种状态要保持 多长时间呢?这种状态的端点留在该状态的持续时间是最长数据分组的生命周期MSL (Maximum Segment Lifetime)的两倍,也称为2MSL。因此,在这段时间内,程序是无法使用这个端口的,因为这个端口资源还没有完全释放。
对于每个TCP 连接实现,都必须选择一个MSL值。在RFC1122文档中建议这个值是2分钟。而源自的Berkeley的实现传统上MSL这个值为30秒。这就意味着 TIME_WAIT状态可能保持1分钟到4分钟之间。而在这段时间内,使用这个端口就可能要到前面所说的那种障碍。

问题产生的原因知道了,那么如何解决呢?套接字的选项中有一个SO_REUSEADDR选项,就可以解决这个问题。SO_REUSEADDR选项允许完全重复的绑定。这个选项通过setsockopt()来进行设置。先来看一下这个函数的定义格式:
#include <sys/types.h>
#include <sys/socket.h>

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

s: 套接字,指向一个打开的套接口描述字
level:级别,指定选项代码的类型。具体类型如下:
SOL_SOCKET: 基本套接口
IPPROTO_IP: IPv4套接口
IPPROTO_IPV6: IPv6套接口
IPPROTO_TCP: TCP套接口
optname:选项名,选项名称
optval: 选项值,是一个指向变量的指针类型
optlen :选项长度,即 optval 的大小
返回值:如果函数执行成功,返回0;如果函数执行失败,返回-1。

因此,可以按照下面的伪代码来实现:

int sockfd;
int cflag;

sockfd =socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sockfd < 0)
{
printf("socket() errorn");
exit(-);
}
cflag = 1;
if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,
(char *)&cflag,sizeof(cflag)) == -1)
{
printf("setsockopt() errorn");
exit(-);
}

上面的代码演示了如何解决地址重复绑定的错误。但这段代码也无疑曝露了一个严重的安全问题,也就端口劫持。因为很有可能出现这种情况:一个程序正在正常地 进行通信,而一个含有恶意的程序利用这项功能,重新绑定了这个端口和地址,进行数据的窃取和篡改。当然在RedHat Linux 9.0 上没有发现有这个漏洞。但是在Windows中却不是这么回事。
alexclark 发表于:2005.11.04 10:48 ::分类: ( 沧海一粒 ) ::阅读:(4710次) :: 评论 (0)

发表评论
标题

在此添加评论
表情符号: smile laughing tongue angry crying sad wassat wink

称呼

邮箱地址(可选)

个人主页(可选)

 authimage


自我介绍
切换风格
新闻聚合
博客日历
文章归档...
最新发表...
最新评论...
最多阅读文章...
最多评论文章...
博客统计...
Blog信息
网站链接...