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小时内删除。