关于独占端口

知道各位有没有安装新的for 2K的PlatformSDK啊,如果安装后,不妨比较一
下一些头文件和VS98原有的头文件的异同,会发现不少有趣的东东喔!有些内
容其实MS早就在之前的平台上就提供了支持,只不过一直没有写入它的头文件
里去,下面就是在WinSock2.h里发现的一个例子:

在新版的WinSock2.h里,多了这么一段定义:

#define SO_EXCLUSIVEADDRUSE ((int)(~SO_REUSEADDR)) /* disallow local address reuse */

从MS的注释也可以看出来了,这个东东是为了防止本地端口被重用的,我
们知道,本来我们是可以向同一个端口绑定两个Socket的,只要使用上面
被“反”掉的那个选项SO_REUSEADDR就可以了,想想看这会发生什么事?我
们可以在一个程序打开POP3端口(服务器端缺省是110,客户端应该设置为
随机选择)收信的同时,运行自己的程序,绑定自己的Socket到同样的端口
上,这时侯你就可以在该程序收信的同时,窃听到信件的内容,包括账户
密码!看起来非常简单,不是吗?可是现实中很多软件并没有采取任何有
效的策略来对付这一手,比如国内著名的某电邮客户端软件F**Mail.

那么我们该怎么防止这种情形在自己的程序运行当中出现?直接的想法是
实时监控本机连接,看看都有些什么端口被绑定了,如果发现窃听程序存
在立刻断开。听起来不错,可是真等你断开连接时可能密码已经泄漏了,
要确保在密码传输前切断连接,需要大量的实时处理工作,就算抛开这些困
难不谈,在Windows平台下去访问一大堆的注册表内容来确定目前活动的端口
就有够烦了。还好,现在有了上面的这个socket选项,一切就变得简单了,
请看如下演示程序:

//Test.cpp : Test exclusive with sockets
//if it's ok then written by Star, else i don't know^_^
//

#include
#include

//if have no the new PlatformSDK, then u need to add the
//define statement to your sourcecode, else remove it
//
#define SO_EXCLUSIVEADDRUSE ((int)(~SO_REUSEADDR))

const u_short EXCLUSIVE_PORT = 110;//or others

void main(int argc, char* argv[])
{
SOCKET sock1, sock2;
int ret;
BOOL val;
WSADATA ws;
struct sockaddr_in in;

//need WinSock 2.0!
if (WSAStartup (2, &ws))
return;

if (LOBYTE (ws.wVersion) - 2)
return;

//make two sockets
sock1 = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
sock2 = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);

val = TRUE;
ret = setsockopt (sock1, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, //set to exclusive
(LPCSTR)&val, 4);

if (ret)
{
//failed....
//do something to clear the error....
return;
}

ZeroMemory (&in, sizeof(in));
in.sin_family = AF_INET;
in.sin_port = htons (EXCLUSIVE_PORT);
in.sin_addr.s_addr = INADDR_ANY;

printf ("Now to bind the first socket to port %d with SO_EXCLUSIVEADDRUSE/n", EXCLUSIVE_PORT);

if (bind (sock1, (const struct sockaddr*)&in, sizeof(in)))
{
//failed...
//do something to clear the error...
closesocket (sock1);
return;
}

printf ("The first socket has been bound to port %d/n", EXCLUSIVE_PORT);

ret = setsockopt (sock2, SOL_SOCKET, SO_REUSEADDR,//try to reuse
(LPCSTR)&val, 4);

if (ret)
{
//failed....
//do something to clear the error....
return;
}

ZeroMemory (&in, sizeof(in));
in.sin_family = AF_INET;
in.sin_port = htons (EXCLUSIVE_PORT);
in.sin_addr.s_addr = INADDR_ANY;

printf ("/nNow to bind the second socket to port %d/n", EXCLUSIVE_PORT);

if (bind (sock2, (const struct sockaddr*)&in, sizeof(in)))
{
if (WSAEADDRINUSE == GetLastError ())
printf ("bind failed, the SO_EXCLUSIVEADDRUSE take effect!/n");
else
{
//failed...
//do something to clear the error...
}
}
else
printf ("What??? I see nothing!!!/n");

closesocket (sock1);
closesocket (sock2);

return;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值