2024-03-23 作业

网络聊天室 

运行代码:
main.c
#include "link.h"
#define SER_PORT 8888
int main(int argc, const char *argv[])
{
	if(argv[1]==NULL){
		printf("请输入IP地址\n");
		return 0;
	}
	//创建套接字文件
	int sfd = socket(AF_INET,SOCK_DGRAM,0);
	if(sfd == -1){
		perror("socket error");
		return -1;
	}
	//设置端口快速重用
	int reuse = 1;
	if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1){
		perror("setsockopt error");
		return -1;
	}
	//创建用户信息头结点
	usermsg_p H = node_head();

	struct sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port=htons(SER_PORT);
	sin.sin_addr.s_addr=inet_addr(argv[1]);

	if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin))==-1){
		perror("bind error");
		return -1;
	}
	H->cin=sin;
	//IO 多路复用
	struct pollfd pfd[2];
	pfd[0].fd = 0;
	pfd[0].events = POLLIN;
	pfd[1].fd = sfd;
	pfd[1].events=POLLIN;

	//接受用户信息所用的结构体
	struct sockaddr_in cin;
	socklen_t socklen = sizeof(cin);
	usermsg user_msg;
	usertext user_text;
	char buf[200]="";
	
	while(1){

		poll(pfd,2,-1);
		/***************输入**************************/
#if 1
		if(pfd[0].revents==POLLIN){
			//输出
			bzero(buf,sizeof(buf));
			fgets(buf,sizeof(buf)-1,stdin);
			buf[strlen(buf)-1]=0;
			ser_allput(H,sfd,buf);
		}
#endif
		/*******************输出*************************/
		if(pfd[1].revents==POLLIN){
			recvfrom(sfd,&user_text,sizeof(user_text),0,(struct sockaddr *)&cin,&socklen);
			switch(user_text.type){
				//上线
			case 0:{
		
					   bzero(buf,sizeof(buf));
					   printf("[%s]登录成功\n",user_text.username);
					   sprintf(buf,"[%s]已上线",user_text.username);
					   ser_allput(H,sfd,buf); 
					   insert_usermsg(H,cin,user_text.username);
				   };break;
				   //转发
			case 1:{
					   	
					    bzero(buf,sizeof(buf));
						sprintf(buf,"[%s]:%s",user_text.username,user_text.text);
						printf("[%s]chat成功\n",user_text.username);
					    ser_output(H,sfd,buf,cin.sin_port); 
						break;
				   };
				   //下线
			case 2:{
					   bzero(buf,sizeof(buf));
					   tail_usermsg(H,cin.sin_port);
					   printf("[%s]已下线\n",user_text.username);
					   sprintf(buf,"[%s]已下线",user_text.username);
					   ser_allput(H,sfd,buf); 
				   };break;

			}
		}
		//输出

	}
	/********************************************/

 
	close(sfd);
	return 0;
}
link.c
#include "link.h"
usermsg_p node_head(){
	
	usermsg_p H=(usermsg_p)malloc(sizeof(usermsg));
	if(NULL==H){
		printf("创建失败\n");
		return NULL;
	}
	H->next=NULL;
	H->front=NULL;
	return H;
}
usermsg_p node_create(struct sockaddr_in cin,char *username){
	usermsg_p new =  (usermsg_p)malloc(sizeof(usermsg));
	if(new==NULL){
		printf("创建新节点失败\n");
		return NULL;
	}
	bzero(new->username,sizeof(new->username));
	new->next=NULL;
	new->front=NULL; 
	return new;
}
  
//插入用户信息 头插
void insert_usermsg(usermsg_p H,struct sockaddr_in cin,char *username){
	if(NULL==H){
		printf("头传入失败\n");
 		return;
	}

	usermsg_p new=node_create(cin,username);
	if(new==NULL){
		printf("创建新节点失败\n");
		return;
	}
	new->next=H->next;
	new->front = H;
	H->next = new;
	new->cin=cin;
	strcpy(new->username,username);
	
}
//用户下线,删除 判断条件 
void tail_usermsg(usermsg_p H,short int port){
	printf("%d %d\n",__LINE__,ntohs(port));
	if(NULL==H){
		printf("指针传入失败\n");
		return;
	}
	if(H->next==NULL){
		return;
	}
	usermsg_p p = H->next;
	while(p!=NULL){
		if(ntohs(port)==ntohs((p->cin).sin_port)){
		printf("%d %d\n",__LINE__,ntohs((p->cin).sin_port));
			p->front->next = p->next;
			if(p->next!=NULL)
				p->next->front = p->front;
			free(p);
			return;
		}
		p=p->next;
	}
	printf("没找到用户数据,删除失败\n");
}

//功能:转发
#if 1
void ser_output(usermsg_p H,int sfd,char *text,short int port){

	if(H==NULL){
		printf("%d link.c 传输失败\n",__LINE__);
		return;
	}
	usermsg_p p = H->next;
	while(p!=NULL){
		if(ntohs((p->cin).sin_port)==ntohs(port)){
			p=p->next;
			continue; 
		}
		sendto(sfd,text,strlen(text)+1,0,(struct sockaddr *)&(p->cin),sizeof(p->cin));
		p=p->next;
	}
}

void ser_allput(usermsg_p H,int sfd,char *text){
	if(NULL==H){
		printf("%d H传入失败\n",__LINE__);
		return;
	}
	if(H->next==NULL){
		return;
	} 
	usermsg_p p = H->next;
	while(p!=NULL){
		sendto(sfd,text,strlen(text)+1,0,(struct sockaddr*)&(p->cin),sizeof(p->cin));
		p=p->next;
	}
}
#endif
//

link.h 
#ifndef __LINK_H__
#define __LINK_H__
#include<myhead.h>

typedef struct usermsg{
	
	char username[20];
	struct sockaddr_in cin;
	struct usermsg *next;
	struct usermsg *front;

}usermsg,*usermsg_p;

typedef struct usertext{

	char type; //客户端状态
	char username[20];
	char text[128];
	
}usertext,*usertext_p;
 
usermsg_p node_head();//创建头结点
usermsg_p node_create(struct sockaddr_in cin,char *username);//新节点、存放用户信息
void insert_usermsg(usermsg_p H,struct sockaddr_in cin,char *username);//插入用户信息
void tail_usermsg(usermsg_p H,short int port);//用户下线,删除
void ser_output(usermsg_p H,int sfd,char *text,short int port);
void ser_allput(usermsg_p H,int sfd,char *text);
#endif
客户端: 
#include<myhead.h>
struct usertext{
	char type;
	char username[20];
	char text[128];
};
int main(int argc, const char *argv[])
{
	if(argv[1]==NULL){
		printf("请输入IP地址\n");
		return 0;
	}
	int cfd = socket(AF_INET,SOCK_DGRAM,0);
	if(cfd == -1){
		perror("socket error");
		return -1;
	}
	//前摇
	struct sockaddr_in sin;
	sin.sin_family = AF_INET;
	struct usertext user_text;

	char buf[200] = "";
	int port=0;
	user_text.type=0;

	printf("请输入用户名>>>");
	fgets(buf,sizeof(buf)-1,stdin);
	buf[strlen(buf)-1]=0;
	user_text.type=0;
	strcpy(user_text.username,buf);
	sin.sin_addr.s_addr = inet_addr(argv[1]);
	printf("请输入服务器端口>>>");
	scanf("%d",&port);
	sin.sin_port = htons(port);
	//发送连接请求
	sendto(cfd,&user_text,sizeof(user_text),0,(struct sockaddr *)&sin,sizeof(sin));
	user_text.type=1;

	//IO多路复用 poll 
	struct pollfd pfd[2];
	pfd[0].fd = 0;
	pfd[0].events = POLLIN; 
	pfd[1].fd = cfd;
	pfd[1].events = POLLIN;
	int i = 0;	
	while(1){
		poll(pfd,2,-1); 
		if(pfd[0].revents==POLLIN){
			fgets(user_text.text,sizeof(user_text.text)-1,stdin);
			if(0==i){i++;continue;}
			user_text.text[strlen(user_text.text)-1]=0;
			if(strcmp(user_text.text,"quit")==0){
				user_text.type = 2;
				sendto(cfd,&user_text,sizeof(user_text),0,(struct sockaddr *)&sin,sizeof(sin));	
				break;
			}
			sendto(cfd,&user_text,sizeof(user_text),0,(struct sockaddr *)&sin,sizeof(sin));	
		}
		if(pfd[1].revents==POLLIN){
			recv(cfd,buf,sizeof(buf)-1,0);
			printf("%s\n",buf);
		}
	}
	close(cfd);

	return 0;
}
运行截图:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值