23111 网络编程 day6

思维导图

23111 网络编程 day6_第1张图片

网络聊天室

服务器

#include

//客户信息结构体
typedef struct
{
	int type;
	char name[20];
	char text[128];
}MSG;

//链表信息结构体
typedef struct node
{
	struct sockaddr_in cin;
	struct node* next;
}Linklist;

int do_send(int sfd,struct sockaddr_in sin);

int do_recv(int sfd,Linklist* head);

int do_chat(int sfd,Linklist* head,MSG msg,struct sockaddr_in cin);

int do_login(int sfd,Linklist* head,MSG msg,struct sockaddr_in cin);

int do_delet(int sfd,Linklist* head,MSG msg,struct sockaddr_in cin);


int main(int argc, const char *argv[])
{
	if(argc<3)
	{
		printf("请输入ip和端口号\n");
		return -1;
	}

	//创建套接字
	int sfd=socket(AF_INET,SOCK_DGRAM,0);
	if(sfd==-1)
	{
		perror("socket error");
		return -1;
	}

	
	//定义服务器的地址信息,用于收发数据
	struct sockaddr_in sin;
	sin.sin_family=AF_INET;
	sin.sin_port=htons(atoi(argv[2]));
	sin.sin_addr.s_addr=inet_addr(argv[1]);

	if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
	{
		perror("bind error");
		return -1;
	}


	pid_t pid=fork();

	if(pid>0)
	{
		//父进程接收数据
		//创建一个容器(链表)
		Linklist* head=(Linklist*)malloc(sizeof(Linklist));
		head->next=NULL;
		do_recv(sfd,head);
	}
	else if(pid==0)
	{
		//子进程发送数据
		do_send(sfd,sin);
	}
	
	//关闭套接字
	close(sfd);


	return 0;
}

//系统发送消息
int do_send(int sfd,struct sockaddr_in sin)
{
	MSG msg;
	while(1)
	{
		bzero(msg.text,128);
		fgets(msg.text,128,stdin);
		msg.text[strlen(msg.text)-1]==0;

		if(sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sizeof(sin))==-1)
		{
			perror("sendto error");
			return -1;
		}
	}
	printf("系统发送消息成功\n");
	return 0;
}

//系统接收客户信息
int do_recv(int sfd,Linklist* head)
{
	MSG msg;
	struct sockaddr_in cin;
	socklen_t socklen=sizeof(cin);

	while(1)
	{
		if(recvfrom(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&cin,&socklen)==-1)
		{
			perror("recvfrom error");
			return -1;
		}

		switch(msg.type)
		{
		case 1:    //用户登录
			{
				do_login(sfd,head,msg,cin);
			}
			break;
		case 2:    //查找用户
			{
				do_chat(sfd,head,msg,cin);
			}
			break;
		case 3:     //删除用户
			{
				do_delet(sfd,head,msg,cin);
			}
			break;
		}
	}
	return 0;
}

//查找
int do_chat(int sfd,Linklist* head,MSG msg,struct sockaddr_in cin)
{
	printf("%s [%s:%d]发送成功\n",msg.name,\
			(char*)inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));

	char buf[1024]="";
	sprintf(buf,"%s:%s",msg.name,msg.text);
	strcpy(msg.text,buf);

	//循环发送消息
	while(head->next!=NULL)
	{
		head=head->next;
		if(memcmp(&cin, &head->cin,sizeof(cin))!=0)
		{
			if(sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&(head->cin),sizeof(head->cin))==-1)
			{
				perror("sendto error");
				return -1;
			}
		}
	}
	return 0;
}

//登录函数
int do_login(int sfd,Linklist* head,MSG msg,struct sockaddr_in cin)
{
	printf("%s [%s:%d]登录成功\n",msg.name,\
			(char*)inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));

	sprintf(msg.text,"***%s登录成功***",msg.name);

	while(head->next!=NULL)
	{
		head=head->next;
		if(sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&(head->cin),sizeof(head->cin))==-1)
		{
			perror("sendto error");
			return -1;
		}
	}
	Linklist* s=(Linklist*)malloc(sizeof(Linklist));
	s->cin=cin;
	s->next=NULL;
	s->next=s;
	return 0;
}

//删除函数
int do_delet(int sfd,Linklist* head,MSG msg,struct sockaddr_in cin)
{
	sprintf(msg.text,"***%s已下线***\n",msg.name);
	
	while(head->next!=NULL)
	{
		if(memcmp(&cin,&head->next->cin,sizeof(cin))==0)
		{
			Linklist* q=head->next;
			head->next=q->next;
			free(q);
		}
		else
		{
			head=head->next;
			if(sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&(head->cin),sizeof(head->cin))==-1)
			{
				perror("sendto error");
				return -1;
			}
		}
	}
	return 0;
}

客户端

#include

//收发信息的结构体
typedef struct 
{
	int type;
	char name[20];
	char text[128];
}MSG;

void handler(int signo)
{
	while(waitpid(-1,NULL,WNOHANG)>0);
}


int do_send(int sfd, MSG msg,struct sockaddr_in sin)
{
	while(1)
	{
		bzero(msg.text,128);
		fgets(msg.text,128,stdin);
		msg.text[strlen(msg.text)-1]=0;

		if(strcmp(msg.text, "quit")==0)
		{
			break;
		}

		if(sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sizeof(sin))==-1)
		{
			perror("sendto error");
			return -1;
		}
	}
}


int do_recv(int sfd,MSG msg)
{
	while(1)
	{
		if(recvfrom(sfd,&msg,sizeof(msg),0,NULL,NULL)==-1)
		{
			perror("recvfrom error");
			return -1;
		}
		printf("%s\n",msg.text);
	}

}


int main(int argc, const char *argv[])
{
	if(argc<3)
	{
		printf("请输入 ip和端口号\n");
		return -1;
	}


	//信号处理函数
	if(signal(SIGCHLD,handler)==SIG_ERR)
	{
		perror("signal error");
		return -1;
	}

	//创建套接字
	int sfd=socket(AF_INET,SOCK_DGRAM,0);
	if(sfd==-1)
	{
		perror("socket error");
		return -1;
	}
	
	//填充IP和端口号信息
	struct sockaddr_in sin;
	sin.sin_family=AF_INET;
	sin.sin_port=htons(atoi(argv[2]));
	sin.sin_addr.s_addr=inet_addr(argv[1]);
	socklen_t addrlen=sizeof(sin);


	//登录
	MSG msg;

	printf("请输入账号>>>");
	fgets(msg.name,20,stdin);
	msg.name[strlen(msg.name)-1]=0;

	//发送信息
	if(sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sizeof(sin))==-1)
	{
		perror("sendto error");
		return -1;
	}


	pid_t pid=fork();

	if(pid>0)
	{
		//父进程获取信息
		do_recv(sfd,msg);
	}
	else if(pid==0)
	{
		//子进程发送信息
		do_send(sfd,msg,sin);

		//退出子进程
		exit(EXIT_SUCCESS);
	}
	

	//关闭套接字
	close(sfd);
	return 0;
}

你可能感兴趣的:(c语言)