day6 网络编程 c语言

该代码示例展示了一个使用UDP协议的简单网络聊天室实现,包括服务器端和客户端程序。服务器端通过多线程处理接收和发送消息,客户端则负责向服务器发送消息并接收服务器广播的消息。用户可以登录、发送聊天消息以及退出聊天室。
摘要由CSDN通过智能技术生成

实现udp的网络聊天室

 

服务器端:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>

#define ERR_MSG(msg) do{\
	perror(msg);\
}while(0)

#define SUC_MSG(msg) do{\
	printf("%s success\n",msg);\
}while(0)

#define SER_PORT 6666
#define SER_IP "192.168.10.104"

struct msg{
	char type;
	char name[20];
	char text[128];
};

char buf[149];
int len = 0;
int cliNum = 0;
struct msg cliData;
struct sockaddr_in serIN;	
int sfd = 0;
int res = 0;
pthread_t tid1,tid2;
struct sockaddr_in cin;
struct sockaddr_in cliIN[1022];

void *send_to_cli(void *arg){
	while(1){	
		bzero(buf,sizeof(buf));
		fgets(buf,sizeof(buf),stdin);
		buf[strlen(buf) - 1] = 0;
		cliData.type = 'S';
		strcpy(cliData.name,"system");
		strcpy(cliData.text,buf);
		bzero(buf,sizeof(buf));
		*buf = cliData.type;
		strcpy(buf+1,cliData.name);
		strcpy(buf+21,cliData.text);
		for(int i = 0; i < cliNum;i++){
			res = sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)(cliIN + i),len);
			if(res < 0){
				ERR_MSG("send to cli");
			}
		}
	}
}
void *recv_from_cli(void *arg){

	while(1){
		bzero(buf,sizeof(buf));
		len = sizeof(cin);
		res = recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cin,&len);
		cliData.type = *buf;
		strcpy(cliData.name,buf+1);
		strcpy(cliData.text,buf+21);
		if(res < 0){
			ERR_MSG("Receive from cli");
		}
		if(res == 0)
		{
			printf("cli is off\n");
		}
		else if(res > 0)
		{	
			if(*buf == 'L'){
				res = write(1,"User ",5);
				res = write(1,buf+1,sizeof(cliData.name));
				printf(" has logged in.\n");
				if(res < 0){
					ERR_MSG("Log in msg");
				}
				cliIN[cliNum] = cin;
				cliNum++;
				*buf = 'L';
				
			}else if(*buf == 'Q'){
				res= write(1,"Client: ",8);
				res = write(1,buf+1,sizeof(cliData.name));
				printf(" has logged off.\n");
				if(res < 0){
					ERR_MSG("Offline message");
				}
				for(int i = 0; i < cliNum; i++){
					if(cliIN[i].sin_port == cin.sin_port){
						for(int j = i;j < cliNum - 1;j++){
							cliIN[j] = cliIN[j+1];
						}
						break;
					}
				}
				cliNum--;
			}else if(*buf == 'C'){
				res = write(1,buf,sizeof(char));
				res = write(1,":",1);
				res = write(1,buf+21,sizeof(buf)-21);
				puts("");
				if(res < 0){
					ERR_MSG("Chat message");
				}
			}
			bzero(buf,sizeof(buf));
			*buf = cliData.type;
			strcpy(buf+1,cliData.name);
			strcpy(buf+21,cliData.text);
			for(int i = 0; i < cliNum;i++){
				if(cliIN[i].sin_port != cin.sin_port)
				{
					len = sizeof(cliIN[i]);
					res = sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cliIN[i],len);
					if(res < 0){
						ERR_MSG("send to cli");
					}
				}
			}
		}
	}
}
int main(int argc, const char *argv[])
{
	sfd = socket(AF_INET,SOCK_DGRAM,0);
	if(sfd < 0){
		ERR_MSG("socket");
	}
	SUC_MSG("server socket");	
	
	//bind the ip
	serIN.sin_family = AF_INET;
	serIN.sin_port = htons(SER_PORT);
	serIN.sin_addr.s_addr = inet_addr(SER_IP);

	if(bind(sfd,(struct sockaddr*)&serIN,sizeof(serIN)) < 0){
		ERR_MSG("bind");
	}
	SUC_MSG("server bind");

	if(pthread_create(&tid1,NULL,send_to_cli,NULL) < 0){
		ERR_MSG("pthread_create");
	}
	if(pthread_create(&tid2,NULL,recv_from_cli,NULL) < 0){
		ERR_MSG("pthread_create");
	}	
	pthread_join(tid1,NULL);
	pthread_join(tid2,NULL);

	if(close(sfd) < 0){
		ERR_MSG("close");
	}


	return 0;
}

客户端

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/select.h>

#define ERR_MSG(msg) do{\
	perror(msg);\
}while(0)

#define SUC_MSG(msg) do{\
	printf("%s success\n",msg);\
}while(0)

#define SER_PORT 6666
#define SER_IP "192.168.10.104"

struct msg{
	char type;
	char name[20];
	char text[128];
};

char buf[149];
int len = 0;
struct msg cliData;
struct sockaddr_in serIN;	
int sfd;
int res;
pthread_t tid1,tid2;

void *send_to_ser(void *arg){
	while(1){	
		bzero(buf,sizeof(buf));
		fgets(buf,sizeof(buf),stdin);
		buf[strlen(buf) - 1] = 0;
		if(strcasecmp(buf,"q") == 0){
			cliData.type = 'Q';
			*buf = cliData.type;
			strcpy(buf+1,cliData.name);
			strcpy(buf+21,cliData.text);
			res = sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&serIN,len);
			if(res < 0){
				ERR_MSG("send to server");
			}
			pthread_cancel(tid2);
			pthread_exit(NULL);
		}else{
			cliData.type = 'C';
			strcpy(cliData.text,buf);
			bzero(buf,sizeof(buf));
			*buf = cliData.type;
			strcpy(buf+1,cliData.name);
			strcpy(buf+21,cliData.text);
			res = sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&serIN,len);
			if(res < 0){
				ERR_MSG("send to server");
			}
		}
	}
}
void *recv_from_ser(void *arg){
	while(1){
		bzero(buf,sizeof(buf));
		res = recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&serIN,&len);
		if(res < 0){
			ERR_MSG("Receive from server");
		}
		if(res == 0)
		{
			printf("Server is off\n");
		}
		else if(res > 0)
		{	
			if(*buf == 'S'){
				res = write(1,"System: ",8);
				res = write(1,buf+21,sizeof(buf)-21);
				puts("");
				if(res < 0){
					ERR_MSG("system message");
				}
			}else if(*buf == 'Q'){
				res = write(1,"Client ",7);
				res = write(1,buf+1,sizeof(cliData.name));
				if(res < 0){
					ERR_MSG("Offline message");
				}
				printf(" is offline\n");
			}else if(*buf == 'C'){
				res = write(1,buf+1,sizeof(cliData.name));
				res = write(1,":",1);
				res = write(1,buf+21,sizeof(buf)-21);
				puts("");
				if(res < 0){
					ERR_MSG("Chat message");
				}
			}else if(*buf == 'L'){
				res = write(1,"Client ",7);
				res = write(1,buf+1,sizeof(cliData.name));
				printf("has logged in.\n");
				if(res < 0){
					ERR_MSG("Log in");
				}
			}
		}
	}
}
int main(int argc, const char *argv[])
{
	sfd = socket(AF_INET,SOCK_DGRAM,0);
	if(sfd < 0){
		ERR_MSG("socket");
	}
	SUC_MSG("cli socket");	

	serIN.sin_family = AF_INET;
	serIN.sin_port = htons(SER_PORT);
	serIN.sin_addr.s_addr = inet_addr(SER_IP);
	len = sizeof(serIN);

	printf("Please log in first:\n");
	bzero(buf,sizeof(buf));
	fgets(cliData.name,sizeof(cliData.name),stdin);
	cliData.name[strlen(cliData.name) - 1] = 0;
	strcpy(cliData.text,"");
	
	cliData.type = 'L';
	strcpy(cliData.text,"");
	*buf = cliData.type;
	strcpy(buf+1,cliData.name);
	strcpy(buf+21,cliData.text);
	res = sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&serIN,len);
	if(res < 0){
		ERR_MSG("Log in failed.");
		return -1;
	}

	if(pthread_create(&tid1,NULL,send_to_ser,NULL) < 0){
		ERR_MSG("pthread_create");
	}
	if(pthread_create(&tid2,NULL,recv_from_ser,NULL) < 0){
		ERR_MSG("pthread_create");
	}


	pthread_join(tid1,NULL);
	pthread_join(tid2,NULL);
	if(close(sfd) < 0){
		ERR_MSG("close");
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值