利用udp创建一个聊天室

lts.h

#ifndef UDP
#define UDP
#include <myhead.h>
#define SER_PORT 8888
#define SER_IP "192.168.8.1"
 
typedef struct Node{
	char username[20];
	struct sockaddr_in cin;
	struct Node *next;
}Node,*NodePtr;
 
typedef struct Message{
	int type;//消息类型   1:login  2:logout  3:chat
	char username[20];
	char text[1024];
}Message;
 
#endif 

客户端

#include "udpAssociate.h"
int cfd;
struct sockaddr_in in;
 
void * udp_send(void *arg){
	Message message;
	printf("请输入用户名:");
	scanf("%s",message.username);
	getchar();
	while(1){
		printf("请输入发送的消息类型:");
		scanf("%d",&message.type);
		getchar();
		if(message.type==1||message.type==2){
			sendto(cfd,&message,sizeof(message),0,(struct sockaddr*)&in,sizeof(in));
		}else if(message.type==3){
			printf("请输入要发送的消息:");
			scanf("%s",message.text);
			getchar();
			sendto(cfd,&message,sizeof(message),0,(struct sockaddr*)&in,sizeof(in));
		}
		printf("发送成功\n");
		if(message.type==2){
			break;
		}
	}
	pthread_exit(NULL);
}
void * udp_recvive(void *arg){
	Message message;
	while(1){
		if(recv(cfd,&message,sizeof(message),0)<=0){
			break;
		}
		if(message.type==3){
			printf("%s:%s\n",message.username,message.text);
		}else{
			printf("收到服务器消息:%s%s\n",message.username,message.text);
		}
	}
	pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
	 // 创建套接字  
    cfd = socket(AF_INET, SOCK_DGRAM, 0);  
    if (cfd < 0) {  
        perror("socket error");  
        return -1;  
    }  
    // 服务器结构体  
    in.sin_family = AF_INET;  
    in.sin_port = htons(SER_PORT);  
    in.sin_addr.s_addr = inet_addr(SER_IP);  
 
	pthread_t pid1=-1,pid2=-1;
	if(pthread_create(&pid1,NULL,udp_send,NULL)!=0){
		perror("pthread_create error");
		return -1;
	}
	if(pthread_create(&pid2,NULL,udp_recvive,NULL)!=0){
		perror("pthread_create error");
		return -1;
	}
 
	pthread_detach(pid1);
	pthread_detach(pid2);
	while(1);
	return 0;
}

服务端

#include "udpAssociate.h"
int cfd;
NodePtr head;
//发送消息标志  1发  0不发
int flag=0;
Message message;
 
void * udp_send(void *arg){
	while(1){
		if(flag){
			if(message.type==1){
				strcpy(message.text,"已登录");
				NodePtr p=head->next;
				while(p){
					sendto(cfd,&message,sizeof(message),0,(struct sockaddr*)&(p->cin),sizeof(p->cin));
					p=p->next;
				}
			}else if(message.type==2){				
				strcpy(message.text,"已下线");
				NodePtr p=head->next;
				while(p){
					sendto(cfd,&message,sizeof(message),0,(struct sockaddr*)&(p->cin),sizeof(p->cin));
					p=p->next;
				}
			}else{
				NodePtr p=head->next;
				while(p){
					sendto(cfd,&message,sizeof(message),0,(struct sockaddr*)&(p->cin),sizeof(p->cin));
					p=p->next;
				}
			}
			printf("发送成功\n");
			flag=0;
		}
	}
	pthread_exit(NULL);
}
 
void * udp_recvive(void *arg){
	struct sockaddr_in cin;
	socklen_t addrlen=sizeof(cin);
	while(1){
		if(recvfrom(cfd,&message,sizeof(message),0,(struct sockaddr*)&cin,&addrlen)==-1){
			break;
		}
		if(message.type==1){
			printf("%s:[%d]\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));
			NodePtr node=(NodePtr)malloc(sizeof(Node));
			strcpy(node->username,message.username);
			node->cin=cin;
			node->next=head->next;
			head->next=node;
		}else if(message.type==2){
			NodePtr p=head;
			while(p->next){
				if(strcmp(p->next->username,message.username)==0){
					NodePtr q=p->next;
					p->next=q->next;
					free(q);
					break;
				}
				p=p->next;
			}
		}
		flag=1;
	}
	pthread_exit(NULL);
}
 
void * broadcast(void *arg){
	Message message;
	while(1){
		strcpy(message.username,"系统广播");
		printf("请输入系统广播消息:");
		scanf("%s",message.text);
		message.type=3;
		NodePtr p=head->next;
		while(p){
			sendto(cfd,&message,sizeof(message),0,(struct sockaddr*)&(p->cin),sizeof(p->cin));
			p=p->next;
		}
		printf("系统广播消息发送成功\n");
	}
}
 
int main(int argc, const char *argv[])
{
	head=(NodePtr)malloc(sizeof(Node));
	head->next=NULL;
	 // 创建套接字  
    cfd = socket(AF_INET, SOCK_DGRAM, 0);  
    if (cfd < 0) {  
        perror("socket error");  
        return -1;  
    }  
    // 服务器结构体  
	struct sockaddr_in sin;
    sin.sin_family = AF_INET;  
    sin.sin_port = htons(SER_PORT);  
    sin.sin_addr.s_addr = inet_addr(SER_IP);  
 
	//bind
	if(bind(cfd,(struct sockaddr*)&sin,sizeof(sin))==-1){
		perror("bind error");
		return -1;
	}
	//创建3个线程
	pthread_t pid1=-1,pid2=-1,pid3=-1;
	if(pthread_create(&pid1,NULL,udp_send,NULL)!=0){
		perror("pthread_create error");
		return -1;
	}
	if(pthread_create(&pid2,NULL,udp_recvive,NULL)!=0){
		perror("pthread_create error");
		return -1;
	}
	if(pthread_create(&pid3,NULL,broadcast,NULL)!=0){
		perror("pthread_create error");
		return -1;
	}
 
	pthread_detach(pid1);
	pthread_detach(pid2);
	pthread_detach(pid3);
 
	while(1);
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值