红联Linux门户
Linux帮助

【unix网络编程第三版】ubuntu端口占用问题

发布时间:2016-07-06 15:43:39来源:linux网站作者:ZeeCoder
《unix网络编程》一书中的代码并不是能直接运行,有时候需要结合各方面的知识来解决,大家在这本书的时候,一定要把代码都跑通,不难你会错过很多学习的机会!
 
1.问题描述
本人在阅读《UNIX网络编程》中,发现运行书中服务器端程序时,返回bind error:Address already in use!
服务器端代码如下:
#include    "unp.h"
#include    <time.h>
int
main(int argc, char **argv)
{
int                 listenfd, connfd;
socklen_t           len;
struct sockaddr_in  servaddr,cliaddr;
char                buff[MAXLINE];
time_t              ticks;
//创建套接字
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
//初始化套接字
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family      = AF_INET;//IPv4协议
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//通配地址,一般为0
servaddr.sin_port        = htons(13);//时间服务端口
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
for ( ; ; ) {
len = sizeof(cliaddr);
connfd = Accept(listenfd, (SA *) &cliaddr, &len);
printf("connection from %s, port %d/n",     inet_ntop(AF_INET,&cliaddr.sin_addr,buff,sizeof(buff)),//将二进制地址转换成点分十进制地址
ntohs(cliaddr.sin_port));//端口好
ticks = time(NULL);
snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
Write(connfd, buff, strlen(buff));
Close(connfd);
}
}
该代码的作用是将TCP套接字绑定到13号端口,以便给客户端发送日期和时间。
 
2.问题解决
2.1.方法一:关闭该端口的进程
我们在运行服务器端代码的时候会出现以下错误:
root@zc:/home/zc/Documents/unp# ./daytimetcpsrv 
bind error: Address already in use
于是查一下netstat来判断那个进程占用了13号端口(netstat -apn | grep 13):
root@zc-Inspiron-N4010:/home/zc/Documents/unp# netstat -apn | grep 13
tcp        0      0 0.0.0.0:13              0.0.0.0:*               LISTEN      6432/xinetd     
tcp        0      1 192.168.191.2:57984     61.135.189.223:80       SYN_SENT    1374/fcitx      
显示xinetd占用了端口13,再来看看哪个进程占用了12端口:
root@zc-Inspiron-N4010:/home/zc/Documents/unp# sudo lsof -i:13
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
xinetd  6432 root    5u  IPv4 208386      0t0  TCP *:daytime (LISTEN)
xinetd  6432 root    6u  IPv4 208387      0t0  UDP *:daytime 
现在,通过sudo kill XXXX就能杀掉这个进程,让13号端口空闲出来了。
 
2.2.解决方案二:设置端口为可重用
在unp一书中,bind函数上提到过“Address already in use”的解决方案。7.5节中通过函数将其设为可重用即可。
int on = 1;
int ret = setsockopt(sock,SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
但是,在我们的程序中,还是不行!
于是,我们细想,xinetd是第一个占用13端口的,它在启动的时候没有设置这个端口可重用,自然我们的程序也没办法重用这个端口,所以,结合上述两个方案,最终的解决方案是:首先kill掉xinetd服务,然后运行我们的程序,再开启xinet,即可。
//首先执行
sudo kill 6432
//然后运行我们的程序
# ./daytimetcpsrv
//再重启xinetd
# service xinetd restart
//这个时候查看13号端口
# sudo lsof -i:13
COMMAND     PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
daytimetc 17791 root    3u  IPv4 4484357      0t0  TCP *:daytime (LISTEN)
xinetd    17837 root    5u  IPv4 4483070      0t0  UDP *:daytime 
问题到这解决了,愉快的使用13号端口把!
 
参考:
1.Linux中的端口占用问题(http://www.linuxdiyf.com/linux/22129.html)
2.Linux 套接字编程中的 5 个隐患(http://www.ibm.com/developerworks/cn/linux/l-sockpit/)
 
本文永久更新地址:http://www.linuxdiyf.com/linux/22130.html