TCP通信: Address already in use

更多资料请点击:我的目录
本篇仅用于记录自己所学知识及应用,代码仍可优化,仅供参考,如果发现有错误的地方,尽管留言于我,谢谢。

程序运行时出现下图报错:
在这里插入图片描述
原因: 端口释放后,需要等待将近30秒的时间,才能再次使用,而在这段时间内再次运行代码,都会出现Address already in use,
从而不能正常运行
解法: 创建套接字之后,设置端口释放后立即就可以被再次使用

	int on=1;
	setsockopt(套接字,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));				//设置端口释放后立即就可以被再次使用

修改好后的版本:在端口断开后能立即再次使用
下面是原码:

/*
	服务器部分:
*/
#include <stdio.h>	
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <pthread.h>

int tcpsock;
int newsock;
void finish()
{
    
    	
	write(newsock,"quit",4);											//当服务器中断,给客户端发送quit
	close(tcpsock);
	close(newsock);
	exit(0);
}

void *transfer()
{
    
    
	char buf[100] = {
    
    0};												//存放客户端发送给指定客户端的消息
	
	while(1)
	{
    
    	
		bzero(buf,100);
		read(newsock,buf,100);
		if(strstr(buf,"quit") != NULL)									//判断时候收到“quit”(客户端中断)
		{
    
    	
			printf("客户端%d退出!!\n",newsock);
			close(newsock);
			exit(0);
		}
		printf("receive %s\n",buf);
	}
}

int main()
{
    
    
	int ret;
	struct sockaddr_in bindaddr;										//定义ipv4地址结构体变量
	bzero(&bindaddr,sizeof(bindaddr));
	bindaddr.sin_family=AF_INET;
	bindaddr.sin_addr.s_addr=inet_addr("192.168.1.157");  				//绑定服务器自己的ip地址
	bindaddr.sin_port=htons(10086); 									//绑定服务器自己的端口号

	struct sockaddr_in clientaddr;
	bzero(&clientaddr,sizeof(clientaddr));
	int addrsize=sizeof(clientaddr);
	
	tcpsock=socket(AF_INET,SOCK_STREAM,0);								//创建tcp套接字
	if(tcpsock==-1)
	{
    
    
		perror("创建tcp套接字!\n");
		return -1;
	}
	
	ret=bind(tcpsock,(struct sockaddr *)&bindaddr,sizeof(bindaddr));	//绑定ip和端口号
	if(ret==-1)
	{
    
    
		perror("绑定失败!\n");
		return -1;
	}
	
	ret=listen(tcpsock,8);												//监听
	if(ret==-1)
	{
    
    
		perror("监听失败!\n");
		return -1;
	}
	
	signal(SIGINT,finish);
	while(1)
	{
    
    
		newsock=accept(tcpsock,(struct sockaddr *)&clientaddr,&addrsize);//接收客户端的连接请求
		if(newsock==-1)
		{
    
    
			perror("接收客户端的连接请求失败!\n");
			return -1;
		}
		
		printf("ip == %s\n",inet_ntoa(clientaddr.sin_addr));
		printf("端口号 == %d\n",ntohs(clientaddr.sin_port));
		printf("新的文件描述符:%d\n",newsock);
		
		pthread_t id;
		pthread_create(&id,NULL,&transfer,NULL);
	}
}
/*
	客户端部分:
*/
#include <stdio.h>	
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <pthread.h>

int tcpsock;	
pthread_t id;
	
void *fun()									
{
    
    
	char recv[100];
	while(1)
	{
    
    
		bzero(recv,100);
		if(read(tcpsock,recv,100))											//接收服务器发送的消息
		{
    
    
			if(strstr(recv,"quit") != NULL)									//判断时候收到“quit”(服务器中断)
			{
    
    	
				printf("服务器出错!\n");
				close(tcpsock);
				exit(0);
			}
			printf("receive %s\n",recv);
		}
	}
}
	
void finish()
{
    
    
	write(tcpsock,"quit",4);												//当客户端中断时,向服务器发送quit
	close(tcpsock);
	pthread_cancel(id);
	exit(0);
}
	
int main()
{
    
    
	int ret;
	char buf[100];
	
	struct sockaddr_in bindaddr;											//定义ipv4地址结构体变量
	bzero(&bindaddr,sizeof(bindaddr));
	bindaddr.sin_family=AF_INET;
	bindaddr.sin_addr.s_addr=inet_addr("192.168.1.157"); 	 				//绑定客户端自己的ip地址
	bindaddr.sin_port=htons(30000); 										//绑定客户端自己的端口号
	
	struct sockaddr_in serveraddr;											//定义结构体变量存放对方(服务器)的ip和端口号
	bzero(&serveraddr,sizeof(serveraddr));
	serveraddr.sin_family=AF_INET;
	serveraddr.sin_addr.s_addr=inet_addr("192.168.1.157");  				//服务器的ip地址
	serveraddr.sin_port=htons(10086); 										//服务器的端口号
	
	tcpsock=socket(AF_INET,SOCK_STREAM,0);									//创建tcp套接字
	if(tcpsock==-1)
	{
    
    
		perror("创建tcp套接字!\n");
		return -1;
	}
		
	ret=bind(tcpsock,(struct sockaddr *)&bindaddr,sizeof(bindaddr));		//绑定ip和端口号
	if(ret==-1)
	{
    
    
		perror("绑定失败!\n");
		return -1;
	}
	
	ret=connect(tcpsock,(struct sockaddr *)&serveraddr,sizeof(serveraddr));	//连接服务器
	if(ret==-1)
	{
    
    
		perror("连接服务器!\n");
		return -1;
	}
	
	signal(SIGINT,finish);
	
	pthread_create(&id,NULL,&fun,NULL);
	
	printf("请输入要发送给服务器的信息!\n");								//发送信息给服务器
	while(1)
	{
    
    
		bzero(buf,100);
		scanf("%s",buf);
		if(strstr(buf,"quit")!=NULL)										//当客户端输入quit退出时,调用finish()函数
		{
    
    
			finish();														//向服务器发送quit
		}
		write(tcpsock,buf,strlen(buf));
	}
	close(tcpsock);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43793181/article/details/108465926