socket报错:bind:address already in use

博客讲述了在TCP Socket编程中遇到的端口占用问题。通过添加setsockopt()函数启用SO_REUSEADDR选项,允许立即重用处于TIME_WAIT状态的端口。TIME-WAIT状态的存在是为了确保被动关闭的一方能正确关闭,并防止新连接接收旧数据包。建议服务端先启动,客户端先关闭,以优化多客户端场景下的交互。
摘要由CSDN通过智能技术生成

写了一个tcp socket包含服务器和客户端,当用Ctrl + C后终止服务端后,再次启动时报错:

bind:address already in use

就是说端口重复占用了,寻思着是Ctrl + C暴力停止,没有调用close关闭socket。

close(server_sockfd);
close(client_sockfd);

加入上述函数后依然报这个错误,看来事情没有我想的那么简单。
这个时候根据进程名和端口号来查进程号,发现都查不到,不由得虎躯一震,背部发凉。

ps -ef | grep tcpServerDemo
lsof -i :8888

如果查找不到,可以试试

sudo lsof -i: 8888

后来查资料发现即使进程终止,socket也会有一个TIME-WAIT状态,它大概持续2-4分钟,当然也可能更长,过了这个时间就会释放这个端口号。
用这个命令可以看到处于TIME-WAIT状态的端口号:

netstat -an | grep 8888

那么怎么才能立即启动而不是等待这个TIME-WAIT结束呢?

	my_addr.sin_family=AF_INET; //设置为IP通信
	my_addr.sin_addr.s_addr=INADDR_ANY;//服务器IP地址--允许连接到所有本地地址上
	my_addr.sin_port=htons(1234); //服务器端口号
    //创建服务器端套接字--IPv4协议,面向连接通信,TCP协议
    if((server_sockfd=socket(PF_INET,SOCK_STREAM,0))<0)
    {
        cout<<"socket error";
        return ;
    }
    //使端口可以重复使用
    int iSockOptVal = 1;
    if (setsockopt(server_sockfd, SOL_SOCKET, SO_REUSEADDR, &iSockOptVal, sizeof(iSockOptVal)) == -1)
    {
        perror("setsockopt fail");
        close(server_sockfd);
        exit(EXIT_FAILURE);
    } 
    //套接字绑定在服务器的网络地址下
    if(bind(server_sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))<0)
    {
        cout<<"bind error";
	perror("bind error:");
        return ;
    }

其实就是添加一个setsockopt()函数,SO_REUSEADDR和iSockOptVal都是设置可重复使用的参数,其中iSockOptVal若为0则表示不能重复使用。
这个时候其实还是有TIME-WAIT,但是不影响我们重复使用同一个端口。

下面来了解一下TIME-WAIT:
这个有存在的必要吗,当然!存在就有它的合理性。
1.用来保证被动关闭的另一端也能正确关闭。
2.防止新启动的端口接收到旧的数据包。
存在的原因具体参考:TIME-WAIT原因

那么客户端和服务端谁先启动呢?
最好服务端,这样客户端发的每一条数据才能有反馈。
谁先关闭呢?
客户端关闭则服务端会收到服务端关闭的通知;但服务端关闭,则客户端需要发送一次请求才能得知服务端已经关闭。
因此先关闭客户端比较好,还有一个原因,这个服务端可能对应多个客户端,当然不能随便因为一个客户端不用了就关闭。

参考:客户端服务端关闭时函数返回值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

、、、、南山小雨、、、、

分享对你有帮助,打赏一下吧!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值