20240119(基于UDP的网络聊天室)作业

服务器端
#include <stdio.h>
#include <stdlib.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>

#define NFDS 2
#define MSGSIZE 1025
struct customer{
    char name[50];
    struct sockaddr_in sin;
	char msgtype;
	char msgbuf[MSGSIZE];
    struct customer * next;
};
struct customer * createCstmNode(){
	return (struct customer *)malloc(sizeof(struct customer));
}


struct customer * insertCstmNode(struct customer * head,struct customer * newCstm){
	newCstm->next=head;
	head=newCstm;
	return head;
}

char * getName(struct sockaddr_in sin,struct customer * head){
	struct customer *p;
	p=head;

	while(p!=NULL){
		if(p->sin.sin_addr.s_addr==sin.sin_addr.s_addr && p->sin.sin_port==sin.sin_port){
			return p->name;
		}
		p=p->next;
	}
	return NULL;
}
struct customer * deleteCstmNode(struct sockaddr_in sin,struct customer * head){
	struct customer * p,* q;
	p=head;
	q=head;
	if(p==NULL){return head;}
	while(p!=NULL){
		if(p->sin.sin_addr.s_addr==sin.sin_addr.s_addr && p->sin.sin_port==sin.sin_port){
			if(p==head){
				head=p->next;
				free(p);
				p=NULL;
				return head;
			}else{
				q->next=p->next;
				free(p);
				p=NULL;
				return head;
			}
		}
		q=p;
		p=p->next;
	}
	return head;
}

void broadcastMsg(int skt,char * cstmName,char * msg,struct customer * head){
	if(head==NULL){
		printf("no client yet\n");
		return;
	}
	if(skt<3){
		printf("selected wrong socket fd\n");
		return;
	}
	if(strlen(msg)<=0){
		printf("blank message\n");
		return;
	}
	struct customer * p=head;
	while(p!=NULL){
		char mb[1076]="";
		strcat(mb,"[");
		strcat(mb,cstmName);
		strcat(mb,"]");
		strcat(mb,msg);
		if(sendto(skt,mb,sizeof(mb),0,(struct sockaddr *)(&(p->sin)),sizeof(p->sin))==-1){
			perror("sentto error");
			continue;
		}
		p=p->next;
	}
}

int main(int argc, const char *argv[])
{
	//----------create socket
	int ssktfd=socket(AF_INET,SOCK_DGRAM,0);
	if(ssktfd==-1){
		perror("socket error");
		return -1;
	}
	//----------form address structure
	struct sockaddr_in sin;
	sin.sin_family=AF_INET;
	sin.sin_port=htons(9999);
	sin.sin_addr.s_addr=inet_addr("192.168.10.110");
	//----------bind address and port to socket
	if(bind(ssktfd,(struct sockaddr *)&sin,sizeof(sin))==-1){
		perror("bind error");
		return -1;
	}
	//----------initialize customer linked list
	struct customer * cstm_head=NULL;

	//----------set all fds for multiplexing
	struct pollfd pfds[NFDS];
	for(int i=0;i<NFDS;i++){
		pfds[i].fd=-1;
		pfds[i].events=0;
	}
	pfds[0].fd=0;
	pfds[0].events=POLLIN;
	pfds[1].fd=ssktfd;
	pfds[1].events=POLLIN;
	while(1){
		int res=poll(pfds,NFDS,-1);
		if(res==-1){
			perror("poll error");
			return -1;
		}else if(res==0){
			printf("timeout\n");
			return -1;
		}
		char buf[128]="";
		//----------fd==0
		if(pfds[0].revents==POLLIN){
			scanf("%s",buf);
			if(strcmp(buf,"quit")==0){
				broadcastMsg(ssktfd,"server","off line",cstm_head);
				break;
			}else{
				broadcastMsg(ssktfd,"server",buf,cstm_head);
			}
		}
		//----------fd==ssktfd
		if(pfds[1].revents==POLLIN){
			char rsvMsgBuf[MSGSIZE]="";
			struct sockaddr_in csin;
			socklen_t len=sizeof(csin);
			if(recvfrom(ssktfd,rsvMsgBuf,MSGSIZE,0,(struct sockaddr *)&csin,&len)==-1){
				perror("recvfrom error");
				break;
			}
		
			if(rsvMsgBuf[0]=='L'){
				char * cstmName=getName(csin,cstm_head);
				if(cstmName==NULL){
					//----------createCstmNode();
					struct customer * cstm;
					cstm=createCstmNode();
					//----------initialize customer node
					strcpy(cstm->name,rsvMsgBuf+1);
					cstm->sin=csin;
					cstm->msgtype=rsvMsgBuf[0];
					bzero(cstm->msgbuf,sizeof(cstm->msgbuf));
					cstm->next=NULL;

					//----------insert node to linked list
					cstm_head=insertCstmNode(cstm_head,cstm);
					//----------broadcast message
					printf("[%s] log in\n",cstm->name);
					broadcastMsg(ssktfd,cstm->name,"logged in",cstm_head);
				}
			}

			if(rsvMsgBuf[0]=='C'){
				//----------get customer name from linked list
				char * cstmName=getName(csin,cstm_head);
				if(cstmName!=NULL){
					broadcastMsg(ssktfd,cstmName,rsvMsgBuf+1,cstm_head);
				}
			}

			if(rsvMsgBuf[0]=='Q'){
				char * cstmName=getName(csin,cstm_head);
				if(cstmName!=NULL){
					broadcastMsg(ssktfd,cstmName,"off line",cstm_head);
					cstm_head=deleteCstmNode(csin,cstm_head);
					printf("[%s] off line\n",cstmName);
				}
			}
		}
	}
	close(ssktfd);
	printf("server off line\n");
	return 0;
}
客户端
#include <stdio.h>
#include <stdlib.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>

#define NFDS 2
#define MSGSIZE 1025
int main(int argc, const char *argv[])
{
	//----------create socket
	int ssktfd=socket(AF_INET,SOCK_DGRAM,0);
	if(ssktfd==-1){
		perror("socket error");
		return -1;
	}
	//----------form address structure
	struct sockaddr_in sin;
	sin.sin_family=AF_INET;
	sin.sin_port=htons(12345);
	sin.sin_addr.s_addr=inet_addr("192.168.10.110");
	//----------bind address and port to socket
	if(bind(ssktfd,(struct sockaddr *)&sin,sizeof(sin))==-1){
		perror("bind error");
		return -1;
	}
	//----------form server address structure
	struct sockaddr_in ssin;
	ssin.sin_family=AF_INET;
	ssin.sin_port=htons(9999);
	ssin.sin_addr.s_addr=inet_addr("192.168.10.110");

	//----------login
	printf("please login with your name >>");
	char nameBuf[50]="";
	scanf(" %s",nameBuf+1);
	nameBuf[0]='L';
	if(sendto(ssktfd,nameBuf,sizeof(nameBuf),0,(struct sockaddr *)(&ssin),sizeof(ssin))==-1){
		perror("sentto error");
		return -1;
	}

	//----------set all fds for multiplexing
	struct pollfd pfds[NFDS];
	for(int i=0;i<NFDS;i++){
		pfds[i].fd=-1;
		pfds[i].events=0;
	}
	pfds[0].fd=0;
	pfds[0].events=POLLIN;
	pfds[1].fd=ssktfd;
	pfds[1].events=POLLIN;
	while(1){
		int res=poll(pfds,NFDS,-1);
		if(res==-1){
			perror("poll error");
			return -1;
		}else if(res==0){
			printf("timeout\n");
			return -1;
		}
		char buf[128]="";
		//----------fd==0
		if(pfds[0].revents==POLLIN){
			scanf("%s",buf+1);
			if(strcmp(buf+1,"quit")==0){
				buf[0]='Q';
				if(sendto(ssktfd,buf,sizeof(buf),0,(struct sockaddr *)(&ssin),sizeof(ssin))==-1){
					perror("sentto error");
					return -1;
				}
				break;
			}
		
			buf[0]='C';
			if(sendto(ssktfd,buf,sizeof(buf),0,(struct sockaddr *)(&ssin),sizeof(ssin))==-1){
				perror("sentto error");
				return -1;
			}
		}
		//----------fd==ssktfd
		if(pfds[1].revents==POLLIN){
			char rsvMsgBuf[MSGSIZE]="";
			struct sockaddr_in csin;
			socklen_t len=sizeof(csin);
			if(recvfrom(ssktfd,rsvMsgBuf,MSGSIZE,0,(struct sockaddr *)&csin,&len)==-1){
				perror("recvfrom error");
				break;
			}
			printf("%s\n",rsvMsgBuf);
		
		}
	}
	close(ssktfd);
	return 0;
}

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值