linux网络编程之绑定端口注意事项及端口复用文档格式.docx
- 文档编号:20976547
- 上传时间:2023-01-26
- 格式:DOCX
- 页数:15
- 大小:328.61KB
linux网络编程之绑定端口注意事项及端口复用文档格式.docx
《linux网络编程之绑定端口注意事项及端口复用文档格式.docx》由会员分享,可在线阅读,更多相关《linux网络编程之绑定端口注意事项及端口复用文档格式.docx(15页珍藏版)》请在冰豆网上搜索。
argc,
charchar
*argv[])
{
char
server_ip[30]
=
"
10.221.20.12"
;
sockfd;
sockfd
socket(AF_INET,
SOCK_DGRAM,
0);
//创建UDP套接字
if(sockfd
0)
perror("
socket"
);
exit(-1);
}
//
初始化本地网络信息
struct
sockaddr_in
my_addr;
bzero(&
my_addr,
sizeof(my_addr));
my_addr.sin_family
AF_INET;
my_addr.sin_port
htons(8000);
my_addr.sin_addr.s_addr
htonl(INADDR_ANY);
第一次绑定端口8000
err_log;
err_log
bind(sockfd,
(struct
sockaddr*)&
if(err_log
!
bind
8000"
close(sockfd);
又一次绑定别的端口9000,
会绑定失败
htons(9000);
9000"
return
0;
程序编译运行后结果如下:
如果客户端想绑定端口号,一定要调用发送信息函数之前绑定(bind)端口,因为在发送信息函数(sendto,或write),系统会自动给当前网络程序分配一个随机端口号,这相当于随机绑定了一个端口号,这里只会分配一次,以后通信就以这个随机端口通信,我们再绑定端口号的话,就会绑定失败。
如果我们放在发送信息函数(sendto,或write)之前绑定,那样程序将以我们绑定的端口号发送信息,不会再随机分配一个端口号。
绑定失败例子(UDP)如下:
dest_addr;
dest_addr,
sizeof(dest_addr));
dest_addr.sin_family
dest_addr.sin_port
htons(8080);
服务器的端口
inet_pton(AF_INET,
server_ip,
&
dest_addr.sin_addr);
send_buf[512]
this
is
for
test"
如果前面没有绑定端口,sendto()系统会随机分配一个端口
sendto(sockfd,
send_buf,
strlen(send_buf),
0,
//发送数据
sendto()后面绑定端口,绑定失败
在上面提到:
一个网络应用程序只能绑定一个端口(一个套接字只能绑定一个端口)。
实际上,默认的情况下,如果一个网络应用程序的一个套接字绑定了一个端口(占用了8000),这时候,别的套接字就无法使用这个端口(8000),验证例子如下:
sockfd_one;
sockfd_one
//创建UDP套接字one
if(sockfd_one
sockfd_one"
设置本地网络信息
端口为8000
绑定,端口为8000
bind(sockfd_one,
close(sockfd_one);
sockfd_two;
sockfd_two
//创建UDP套接字two
if(sockfd_two
sockfd_two"
新套接字sockfd_two,继续绑定8000端口,绑定失败
因为8000端口已被占用,默认情况下,端口没有释放,无法绑定
bind(sockfd_two,
close(sockfd_two);
那如何让sockfd_one,sockfd_two两个套接字都能成功绑定8000端口呢?
这时候就需要要到端口复用了。
端口复用允许在一个应用程序可以把n个套接字绑在一个端口上而不出错。
设置socket的SO_REUSEADDR选项,即可实现端口复用:
opt
1;
sockfd为需要端口复用的套接字
setsockopt(sockfd,
SOL_SOCKET,
SO_REUSEADDR,
(const
voidvoid
*)&
opt,
sizeof(opt));
SO_REUSEADDR可以用在以下四种情况下。
(摘自《Unix网络编程》卷一,即UNPv1)
1、当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时,而你启动的程序的socket2要占用该地址和端口,你的程序就要用到该选项。
2、SO_REUSEADDR允许同一port上启动同一服务器的多个实例(多个进程)。
但每个实例绑定的IP地址是不能相同的。
在有多块网卡或用IPAlias技术的机器可以测试这种情况。
3、SO_REUSEADDR允许单个进程绑定相同的端口到多个socket上,但每个socket绑定的ip地址不同。
这和2很相似,区别请看UNPv1。
4、SO_REUSEADDR允许完全相同的地址和端口的重复绑定。
但这只用于UDP的多播,不用于TCP。
需要注意的是,设置端口复用函数要在绑定之前调用,而且只要绑定到同一个端口的所有套接字都得设置复用:
sockfd_one,
sockfd_two都要设置端口复用
在sockfd_one绑定bind之前,设置其端口复用
setsockopt(
SOL_SOCKET,SO_REUSEADDR,
sizeof(opt)
在sockfd_two绑定bind之前,设置其端口复用
sockfd_two,
SOL_SOCKET,SO_REUSEADDR,(const
端口复用完整代码如下:
新套接字sockfd_two,继续绑定8000端口,成功
同时,这n个套接字发送信息都正常,没有问题。
但是,这些套接字并不是所有都能读取信息,只有最后一个套接字会正常接收数据。
下面,我们在之前的代码上,添加两个线程,分别负责接收sockfd_one,sockfd_two的信息:
pthread.h>
线程1的回调函数
*recv_one(voidvoid
*arg)
printf("
===========recv_one==============\n"
(int
)arg;
while
(1){
recv_len;
recv_buf[512]
client_addr;
cli_ip[INET_ADDRSTRLEN]
//INET_ADDRSTRLEN=16
socklen_t
cliaddr_len
sizeof(client_addr);
recv_len
recvfrom(sockfd,
recv_buf,
sizeof(recv_buf),
client_addr,
cliaddr_len);
inet_ntop(AF_INET,
client_addr.sin_addr,
cli_ip,
INET_ADDRSTRLEN);
\nip:
%s
port:
%d\n"
cli_ip,
ntohs(client_addr.sin_port));
===========
data(%d):
%s\n"
recv_len,recv_buf);
NULL;
线程2的回调函数
*recv_two(voidvoid
+++++++++recv_two++++++++++++++\n"
XX文库-让每个人平等地提升自我
sizeof(client_addr)
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- linux 网络 编程 绑定 端口 注意事项