地址已经被使用——Address already in use(来自《后台开发:核心技术于应用实践》)
書本P260例7.3中
server如果被第二次啟動,就會出現如下錯誤:
bind:Address already in use
解決方案如下:
首先刪除所有的.o文件,然后對
server代碼修改如下:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>
#define DEFAULT_PORT 6666
int main( int argc, char ** argv){
? ? int serverfd,acceptfd; /* 監聽socket: serverfd,數據傳輸socket: acceptfd */
? ? struct sockaddr_in my_addr; /* 本機地址信息 */
? ? struct sockaddr_in their_addr; /* 客戶地址信息 */
? ? unsigned int sin_size, myport=6666, lisnum=10;
? ? if ((serverfd = socket(AF_INET , SOCK_STREAM, 0)) == -1) {
? ? ? ?perror("socket" );
? ? ? ?return -1;
? ? }
? ? printf("socket ok \n");
? ? my_addr.sin_family=AF_INET;
? ? my_addr.sin_port=htons(DEFAULT_PORT);
? ? my_addr.sin_addr.s_addr = INADDR_ANY;
? ? int on=1; ?
? ? if((setsockopt(serverfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)))<0) ?
? ? { ?
? ? ? ? perror("setsockopt failed"); ?
? ? ? ? exit(EXIT_FAILURE); ?
? ? } ?
? ? bzero(&(my_addr.sin_zero), 0);
? ? if (bind(serverfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr )) == -1) {
? ? ? ? perror("bind" );
? ? ? ? return -2;
? ? }
? ? printf("bind ok \n");
? ? if (listen(serverfd, lisnum) == -1) {
? ? ? ? perror("listen" );
? ? ? ? return -3;
? ? }
? ? printf("listen ok \n");
fd_set client_fdset;/*監控文件描述符集合*/
int maxsock; ? ? ? ? ? ?/*監控文件描述符中最大的文件號*/
struct timeval tv;/*超時返回時間*/
int client_sockfd[5]; ? /*存放活動的sockfd*/
bzero((void*)client_sockfd,sizeof(client_sockfd));
int conn_amount = 0; ? ?/*用來記錄描述符數量*/
maxsock = serverfd;
char buffer[1024];
int ret=0;
while(1){
/*初始化文件描述符號到集合*/
FD_ZERO(&client_fdset);
/*加入服務器描述符*/
FD_SET(serverfd,&client_fdset);
/*設置超時時間*/
tv.tv_sec = 30; /*30秒*/
tv.tv_usec = 0;
/*把活動的句柄加入到文件描述符中*/
for(int i = 0; i < 5; ++i){
/*程序中Listen中參數設為5,故i必須小于5*/
? ?if(client_sockfd[i] != 0){
? ? ? ?FD_SET(client_sockfd[i], &client_fdset);
? ?}
? ? ?}
/*printf("put sockfd in fdset!\n");*/
/*select函數*/
ret = select(maxsock+1, &client_fdset, NULL, NULL, &tv);
if(ret < 0){
? ?perror("select error!\n");
? ?break;
}
else if(ret == 0){
? ?printf("timeout!\n");
? ?continue;
}
/*輪詢各個文件描述符*/
for(int i = 0; i < conn_amount; ++i){
/*FD_ISSET檢查client_sockfd是否可讀寫,>0可讀寫*/
? ?if(FD_ISSET(client_sockfd[i], &client_fdset)){
? ? ? ?printf("start recv from client[%d]:\n",i);
? ? ? ?ret = recv(client_sockfd[i], buffer, 1024, 0);
? ? ? ?if(ret <= 0){
? ?printf("client[%d] close\n", i);
? ?close(client_sockfd[i]);
? ?FD_CLR(client_sockfd[i], &client_fdset);
? ?client_sockfd[i] = 0;
? ? ? ?}
? ? ? ?else{
printf("recv from client[%d] :%s\n", i, buffer);
? ? ? ?}
? ?}
}
/*檢查是否有新的連接,如果收,接收連接,加入到client_sockfd中*/
if(FD_ISSET(serverfd, &client_fdset)){
? ?/*接受連接*/
? ?struct sockaddr_in client_addr;
? ? ? ? size_t size = sizeof(struct sockaddr_in);
int sock_client = accept(serverfd, (struct sockaddr*)(&client_addr), (unsigned int*)(&size));
if(sock_client < 0){
perror("accept error!\n");
continue;
}
/*把連接加入到文件描述符集合中*/
if(conn_amount < 5){
client_sockfd[conn_amount++] = sock_client;
bzero(buffer,1024);
strcpy(buffer, "this is server! welcome!\n");
send(sock_client, buffer, 1024, 0);
printf("new connection client[%d] %s:%d\n", conn_amount, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
bzero(buffer,sizeof(buffer));
ret = recv(sock_client, buffer, 1024, 0);
if(ret < 0){
? ?perror("recv error!\n");
? ?close(serverfd);
? ?return -1;
}
printf("recv : %s\n",buffer);
if(sock_client > maxsock){
maxsock = sock_client;
}
else{
? ?printf("max connections!!!quit!!\n");
? ?break;
}
? ?}
? }
}
for(int i = 0; i < 5; ++i){
if(client_sockfd[i] != 0){
? ?close(client_sockfd[i]);
}
}
? ?printf("serverfd = %d\n",serverfd);
? ?printf("acceptfd = %d\n",acceptfd);
close(serverfd);
return 0;
}
?
client代碼不變
然后對server和client代碼進行重新編譯即可
總結
以上是生活随笔為你收集整理的地址已经被使用——Address already in use(来自《后台开发:核心技术于应用实践》)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ANSYS提取刚度矩阵
- 下一篇: debian/ubuntu19.10下安