socket报错:bind:address already in use
报错 in socket use already bind address
2023-09-14 09:12:44 时间
写了一个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
后来查资料发现即使进程终止,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原因
那么客户端和服务端谁先启动呢?
最好服务端,这样客户端发的每一条数据才能有反馈。
谁先关闭呢?
客户端关闭则服务端会收到服务端关闭的通知;但服务端关闭,则客户端需要发送一次请求才能得知服务端已经关闭。
因此先关闭客户端比较好,还有一个原因,这个服务端可能对应多个客户端,当然不能随便因为一个客户端不用了就关闭。
相关文章
- ORA-00447: fatal error in background process ORACLE 报错 故障修复 远程处理
- ORA-26688: missing key in LCR ORACLE 报错 故障修复 远程处理
- ORA-27103: internal error ORACLE 报错 故障修复 远程处理
- ORA-29477: SQL statement size in bytes is too big ORACLE 报错 故障修复 远程处理
- ORA-29531: no method string in class string ORACLE 报错 故障修复 远程处理
- ORA-30333: dimension does not exist ORACLE 报错 故障修复 远程处理
- ORA-39289: Cannot add or drop local index partition or subpartition: string ORACLE 报错 故障修复 远程处理
- ORA-48447: The input path [string] does not contain any ADR homes ORACLE 报错 故障修复 远程处理
- MySQL Error number: MY-010127; Symbol: ER_FAIL_SETUID; SQLSTATE: HY000 报错 故障修复 远程处理
- ORA-64146: Nonblocking alter XMLIndex error ORACLE 报错 故障修复 远程处理
- ORA-01071: cannot perform operation without starting up ORACLE ORACLE 报错 故障修复 远程处理
- ORA-02222: invalid PCTINCREASE storage option value ORACLE 报错 故障修复 远程处理
- MySQL Error number: MY-011754; Symbol: ER_LDAP_AUTH_SETTING_USERNAME; SQLSTATE: HY000 报错 故障修复 远程处理
- ORA-07593: ssprprv: Error release privileges ORACLE 报错 故障修复 远程处理
- ORA-09756: osnpns: no port in the name server. ORACLE 报错 故障修复 远程处理
- ORA-12505: TNS:listener does not currently know of SID given in connect descriptor ORACLE 报错 故障修复 远程处理
- ORA-13028: Invalid Gtype in the SDO_GEOMETRY object ORACLE 报错 故障修复 远程处理
- ORA-13412: invalid scale parameterstring ORACLE 报错 故障修复 远程处理
- MySQL Error number: MY-013764; Symbol: ER_PLUGIN_INVALID_TABLE_DEFINITION; SQLSTATE: HY000 报错 故障修复 远程处理
- in Neo4j查询:使用Not In操作(neo4j查询not)
- 提升Oracle中IN操作的效率(oracle的in效率)
- MySQL中的Out和In操作一个简单的指南(mysql中out in)