Addressalreadyinuse的解决⽅法
当客户端保持着与服务器端的连接,这时服务器端断开,再开启服务器时会出现: Address already in usr
可以⽤netstat -anp | more 可以看到客户端还保持着与服务器的连接(还在使⽤服务器bind的端⼝)。这是由于client没有执⾏close,连接还会等待client的FIN包⼀段时间。解决⽅法是使⽤setsockopt,使得socket可以被重⽤,是最常⽤的服务器编程要点。具体的做法为是,在socket调⽤和bind调⽤之间加上⼀段对socket的设置:
int opt = 1;
setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
附:setsockopt的⽤法。
setsockopt(设置socket状态)
相关函数
getsockopt
表头⽂件
#include;
#include;
定义函数
int setsockopt(int s,int level,int optname,const void * optval,,socklen_toptlen);
函数说明
setsockopt()⽤来设置参数s所指定的socket状态。参数level代表欲设置的⽹络层,⼀般设成SOL_SOCKET以存取socket层。参数optname代表欲设置的选项,有下列⼏种数值:
SO_DEBUG 打开或关闭排错模式
SO_REUSEADDR 允许在bind()过程中本地地址可重复使⽤
SO_TYPE 返回socket形态。
SO_ERROR 返回socket已发⽣的错误原因
SO_DONTROUTE 送出的数据包不要利⽤路由设备来传输。
SO_BROADCAST 使⽤⼴播⽅式传送
SO_SNDBUF 设置送出的暂存区⼤⼩
SO_RCVBUF 设置接收的暂存区⼤⼩
SO_KEEPALIVE 定期确定连线是否已终⽌。
SO_OOBINLINE 当接收到OOB 数据时会马上送⾄标准输⼊设备
SO_LINGER 确保数据安全且可靠的传送出去。
参数
optval代表欲设置的值,参数optlen则为optval的长度。
返回值
成功则返回0,若有错误则返回-1,错误原因存于errno。
附加说明
EBADF 参数s并⾮合法的socket处理代码
ENOTSOCK 参数s为⼀⽂件描述词,⾮socket
ENOPROTOOPT 参数optname指定的选项不正确。
EFAULT 参数optval指针指向⽆法存取的内存空间
我也是刚开始学习socket⽹络编程,就在同学那搞到⼀个完整版的socket,我在centos上的eclipse下进⾏了编译,就是总出现Address already in use,后来发现了⼀篇博客,就是下⽂,试了试还是没⽤,结果就想⼀定是进程没有杀⼲净,所以就在eclipse下file⾥到了restart,试了试果然好使!不过本⼈觉得下⾯⼀篇⽂章还是很好的!
很多socket编程的初学者可能会遇到这样的问题:如果先ctrl+c结束服务器端程序的话,再次启动服务器就会出现Address already in use这个错误,或者你的程序在正常关闭服务器端socket后还是有这个问题。正如下⾯的这段简单的socket程序。
server.c
[c-sharp]
1. #include <sys/types.h>
2. #include <sys/socket.h>
3. #include <stdio.h>
4. #include <netinet/in.h>
5. #include <arpa/inet.h>
6. #include <unistd.h>
7. #include <stdlib.h>
8.
9. #define BUFFER_SIZE 40
10.
11. int main()
12. {
13. char buf[BUFFER_SIZE];
14. int server_sockfd, client_sockfd;
15. int sin_size=sizeof(struct sockaddr_in);
16. struct sockaddr_in server_address;
17. struct sockaddr_in client_address;
18. memset(&server_address,0,sizeof(server_address));
19. server_address.sin_family = AF_INET;
20. server_address.sin_addr.s_addr = INADDR_ANY;
21. server_address.sin_port = htons(12000);
22. // 建⽴服务器端socket
23. if((server_sockfd = socket(AF_INET, SOCK_STREAM, 0))<0)
24. {
25. perror("server_sockfd creation failed");
26. exit(EXIT_FAILURE);
27. }
28. // 将套接字绑定到服务器的⽹络地址上
29. if((bind(server_sockfd,(struct sockaddr *)&server_address,sizeof(struct sockaddr)))<0)
30. {
31. perror("server socket bind failed");
32. exit(EXIT_FAILURE);
33. }
34. // 建⽴监听队列
35. listen(server_sockfd,5);
36. // 等待客户端连接请求到达
37. client_sockfd=accept(server_sockfd,(struct sockaddr *)&client_address,(socklen_t*)&sin_size);
38. if(client_sockfd<0)
39. {
40. perror("accept client socket failed");
41. exit(EXIT_FAILURE);
42. }
43. // 接收客户端数据
44. if(recv(client_sockfd,buf,BUFFER_SIZE,0)<0)
45. {
46. perror("recv client data failed");
47. exit(EXIT_FAILURE);
48. }
49. printf("receive from client:%s/n",buf);
50. // 发送数据到客户端
51. if(send(client_sockfd,"I have received your message.",BUFFER_SIZE,0)<0)
52. {
53. perror("send failed");
54. exit(EXIT_FAILURE);
55. }
56. close(client_sockfd);
57. close(server_sockfd);
58. exit(EXIT_SUCCESS);
59. }
[c-sharp]
1. #include <sys/types.h>
2. #include <sys/socket.h>
3. #include <stdio.h>
4. #include <netinet/in.h>
5. #include <arpa/inet.h>
6. #include <unistd.h>
7. #include <stdlib.h>
8.
9. #define BUFFER_SIZE 40
10.
11. int main()
12. {
13. char buf[BUFFER_SIZE];
14. int server_sockfd, client_sockfd;
15. int sin_size=sizeof(struct sockaddr_in);
16. struct sockaddr_in server_address;
17. struct sockaddr_in client_address;
18. memset(&server_address,0,sizeof(server_address));
19. server_address.sin_family = AF_INET;
20. server_address.sin_addr.s_addr = INADDR_ANY;
21. server_address.sin_port = htons(12000);
22. // 建⽴服务器端socket
23. if((server_sockfd = socket(AF_INET, SOCK_STREAM, 0))<0)
24. {
25. perror("server_sockfd creation failed");
26. exit(EXIT_FAILURE);
27. }
28. // 将套接字绑定到服务器的⽹络地址上
29. if((bind(server_sockfd,(struct sockaddr *)&server_address,sizeof(struct sockaddr)))<0)
30. {
31. perror("server socket bind failed");
32. exit(EXIT_FAILURE);
33. }
34. // 建⽴监听队列
35. listen(server_sockfd,5);
36. // 等待客户端连接请求到达
37. client_sockfd=accept(server_sockfd,(struct sockaddr *)&client_address,(socklen_t*)&sin_size);
38. if(client_sockfd<0)
39. {
40. perror("accept client socket failed");
41. exit(EXIT_FAILURE);
42. }
43. // 接收客户端数据
44. if(recv(client_sockfd,buf,BUFFER_SIZE,0)<0)
45. {
46. perror("recv client data failed");
47. exit(EXIT_FAILURE);
48. }
49. printf("receive from client:%s/n",buf);
50. // 发送数据到客户端
51. if(send(client_sockfd,"I have received your message.",BUFFER_SIZE,0)<0)
52. {
53. perror("send failed");
54. exit(EXIT_FAILURE);
55. }
56. close(client_sockfd);
57. close(server_sockfd);
58. exit(EXIT_SUCCESS);
59. }
client.c
[c-sharp]
1. #include <sys/types.h>
2. #include <sys/socket.h>
3. #include <stdio.h>
4. #include <netinet/in.h>
5. #include <arpa/inet.h>
6. #include <unistd.h>
7. #include <stdlib.h>
8.
9. #define BUFFER_SIZE 40
10.
11. int main()
12. {
13. char buf[BUFFER_SIZE];
14. int client_sockfd;
15. int len;
16. struct sockaddr_in address;// 服务器端⽹络地址结构体
17. int result;
18. client_sockfd = socket(AF_INET, SOCK_STREAM, 0);// 建⽴客户端socket
19. address.sin_family = AF_INET;
20. address.sin_addr.s_addr = inet_addr("127.0.0.1");
21. address.sin_port = htons(12000);
22. len = sizeof(address);
23. // 与远程服务器建⽴连接
24. result = connect(client_sockfd, (struct sockaddr *)&address, len);
25. if(result<0)
26. {
27. perror("connect failed");
28. exit(EXIT_FAILURE);
29. }
30. printf("Please input the message:");
31. scanf("%s",buf);
32. send(client_sockfd,buf,BUFFER_SIZE,0);
33. recv(client_sockfd,buf,BUFFER_SIZE,0);
34. printf("receive data from server: %s/n",buf);
35. close(client_sockfd);
36. return 0;
37. }
[c-sharp]
1. #include <sys/types.h>
2. #include <sys/socket.h>
3. #include <stdio.h>
4. #include <netinet/in.h>
5. #include <arpa/inet.h>
6. #include <unistd.h>
7. #include <stdlib.h>
8.
9. #define BUFFER_SIZE 40
10.
11. int main()
12. {
13. char buf[BUFFER_SIZE];
14. int client_sockfd;
15. int len;
16. struct sockaddr_in address;// 服务器端⽹络地址结构体
17. int result;
18. client_sockfd = socket(AF_INET, SOCK_STREAM, 0);// 建⽴客户端socket
19. address.sin_family = AF_INET;
20. address.sin_addr.s_addr = inet_addr("127.0.0.1");
21. address.sin_port = htons(12000);
22. len = sizeof(address);
23. // 与远程服务器建⽴连接
24. result = connect(client_sockfd, (struct sockaddr *)&address, len);
25. if(result<0)
26. {
27. perror("connect failed");
28. exit(EXIT_FAILURE);
29. }
30. printf("Please input the message:");
31. scanf("%s",buf);
32. send(client_sockfd,buf,BUFFER_SIZE,0);
33. recv(client_sockfd,buf,BUFFER_SIZE,0);
34. printf("receive data from server: %s/n",buf);
35. close(client_sockfd);
36. return 0;
37. }
在成功的运⾏了第⼀次之后,当你再次启动服务器端程序时,./server就变得邪恶起来,在bind()这个函数中居然出现了Address already in use这个错误。
bind 普遍遭遇的问题是试图绑定⼀个已经在使⽤的端⼝。该陷阱是也许没有活动的套接字存在,但仍然禁⽌绑定端⼝(bind 返回EADDRINUSE),它由 TCP 套接字状态 TIME_WAIT 引起。该状态在套接字关闭后约保留 2 到 4 分钟。在 TIME_WAIT 状态退出之后,套接字被删除,该地址才能被重新绑定⽽不出问题。
等待 TIME_WAIT 结束可能是令⼈恼⽕的⼀件事,特别是如果您正在开发⼀个套接字服务器,就需要停⽌服务器来做⼀些改动,然后重启。幸运的是,有⽅法可以避开 TIME_WAIT 状态。可以给套接字应⽤ SO_REUSEADDR 套接字选项,以便端⼝可以马上重⽤。
考虑清单 3 的例⼦。在绑定地址之前,我以 SO_REUSEADDR 选项调⽤ setsockopt。为了允许地址重⽤,我设置整型参数(on)为 1 (不然,可以设为 0 来禁⽌地址重⽤)。
按照IBM的做法,我重新改写了server.c的代码。
server.c
recv函数[c-sharp]
1. #include <sys/types.h>
2. #include <sys/socket.h>
3. #include <stdio.h>
4. #include <netinet/in.h>
5. #include <arpa/inet.h>
6. #include <unistd.h>
7. #include <stdlib.h>
8.
9. #define BUFFER_SIZE 40
10.
11. int main()
12. {
13. char buf[BUFFER_SIZE];
14. int server_sockfd, client_sockfd;
15. int sin_size=sizeof(struct sockaddr_in);
16. struct sockaddr_in server_address;
17. struct sockaddr_in client_address;
18. memset(&server_address,0,sizeof(server_address));
19. server_address.sin_family = AF_INET;
20. server_address.sin_addr.s_addr = INADDR_ANY;
21. server_address.sin_port = htons(12000);
22. // 建⽴服务器端socket
23. if((server_sockfd = socket(AF_INET, SOCK_STREAM, 0))<0)
24. {
25. perror("server_sockfd creation failed");
26. exit(EXIT_FAILURE);
27. }
28. // 设置套接字选项避免地址使⽤错误
29. int on=1;
30. if((setsockopt(server_sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)))<0)
31. {
32. perror("setsockopt failed");
33. exit(EXIT_FAILURE);
34. }
35. // 将套接字绑定到服务器的⽹络地址上
36. if((bind(server_sockfd,(struct sockaddr *)&server_address,sizeof(struct sockaddr)))<0)
37. {
38. perror("server socket bind failed");
39. exit(EXIT_FAILURE);
40. }
41. // 建⽴监听队列
42. listen(server_sockfd,5);
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论