网络编程-7

本文介绍了使用socket编程实现的系统,用户登录、发送群聊信息以及在线状态变化都会实时同步给其他用户。主要涉及数据结构的设计、节点管理以及多路复用的socket通信机制。
摘要由CSDN通过智能技术生成

项目需求:

  1. 如果有用户登录,其他用户可以收到这个人的登录信息
  2. 如果有人发送信息,其他用户可以收到这个人的群聊信息
  3. 如果有人下线,其他用户可以收到这个人的下线信息
  4. 服务器可以发送系统信息
    #include <myhead.h>
    
    typedef struct msgtyp
    {
    	char type;
    	char usrname[20];
    	char msgtext[1024];
    }msg_t;
    
    typedef struct datatype
    {
    	char name[20];
    	struct sockaddr_in cin;	
    }data_t;
    typedef struct node 
    {
    	union 
    	{
    		struct node *tail;
    		data_t data;
    	};
    	struct node* next;
    }node,*node_p;
    node_p create_head()
    {
    	node_p H=(node_p)malloc(sizeof(node));
    	if(H==NULL)
    	{
    		printf("空间申请失败\n");
    		return NULL;
    	}
    	H->next = NULL;
    	H->tail = H;
    	return H;
    }
    int insert_tail(node_p H,data_t data)
    {
    	if(H==NULL)
    	{
    		printf("入参为空\n");
    		return -1;
    	}
    	node_p new=(node_p)malloc(sizeof(node));
    	if(new==NULL)
    	{
    		printf("空间申请失败\n");
    		return -1;
    	}
    	new->data = data;
    	H->tail->next = new;
    	H->tail = new;
    	return 1;
    }
    
    
    int main(int argc, const char *argv[])
    {
    
     unsigned short SER_PORT;
     char SER_IP[20]="";
     
     printf("服务器ip:");
     scanf("%s",SER_IP);              
     printf("服务器端口号:");
     scanf("%hd",&SER_PORT);
    
    
    	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(SER_PORT);
    	sin.sin_addr.s_addr = inet_addr(SER_IP);
    	if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1) 
    	{
    		perror("bind error");
    		return -1;
    	}
    	fd_set readfds,tempfds;
    	FD_ZERO(&readfds);
    	FD_SET(0,&readfds);
    	FD_SET(sfd,&readfds);
    
    	int maxfd = sfd;
    	struct sockaddr_in cin_arr[1024];
    	struct sockaddr_in cin;
    	socklen_t c_socklen=sizeof(cin);       
    	node_p H=create_head();
    	data_t data;
    	msg_t msgbuf;
    	//	bzero(data,sizeof(data));
    	while(1)
    	{
    		tempfds = readfds;
    
    		int res = select(maxfd+1,&tempfds,NULL,NULL,NULL);
    		if(res == 0)
    		{
    			printf("time out \n");
    			return -1;
    		}
    		else if(res == -1)
    		{
    			perror("select error");
    			return -1;
    		}
    
    		for(int i=0; i<=maxfd;i++)
    		{
    			if(!FD_ISSET(i,&tempfds))
    				continue;
    			if( i == sfd )
    			{
    
    				recvfrom(sfd,&msgbuf,sizeof(msgbuf),0,(struct sockaddr*)&cin,&c_socklen);
    				//		  struct sockaddr_in cin_send =cin ;
    				//		  socklen_t cin_send =sizeof(cin_send);
    				char send_name[20];
    				strcpy(send_name,msgbuf.usrname);
    				if( msgbuf.type == 'L' )       //登录
    				{
    					data_t data;
    					strcpy(data.name,msgbuf.usrname);
    					data.cin = cin;
    					insert_tail(H,data);
    					//需要判断一下注册的名字是否存在
    					strcat(msgbuf.msgtext,"success");
    
    					sendto(sfd,&msgbuf,sizeof(msgbuf),0,(struct sockaddr*)&cin,sizeof(cin));
    				}
    				if( msgbuf.type == 'C' )
    				{
    					//data_t data;
    					node_p p=H->next;
    					while(p!=NULL)
    					{
    
    						if(strcmp(send_name,p->data.name)==0)
    						{	
    							p=p->next;
    						}
    						else
    						{
    							cin = p->data.cin;
    							sendto(sfd,&msgbuf,sizeof(msgbuf),0,(struct sockaddr*)&cin,sizeof(cin));
    
    							p=p->next;
    						}
    					}
    					printf("send success\n");
    				}
    
    
    
    			}
    
    			else if(i == 0)
    			{	
    				msgbuf.type='C';
    				strcpy(msgbuf.usrname,"service");
    				fgets(msgbuf.msgtext, sizeof(msgbuf.msgtext), stdin);
    				msgbuf.msgtext[strlen(msgbuf.msgtext)-1] = 0;
    				node_p p=H->next;
    				while(p!=NULL)
    				{
    					cin = p->data.cin;
    					sendto(sfd,&msgbuf,sizeof(msgbuf),0,(struct sockaddr*)&cin,sizeof(cin));
    					p=p->next;
    
    				}
    				printf("send success\n");
    			}
    		}
    
    
    	}
    
    
    return 0;
    }
    
    #include <myhead.h>
    typedef struct msgtyp
    {
    	char type;
    	char usrname[20];
    	char msgtext[1024];
    }msg_t;
    
    int main(int argc, const char *argv[])
    {
    	unsigned short CLI_PORT;
    	unsigned short SER_PORT;
    	char SER_IP[20]="";
    	char CLI_IP[20]="";
    	printf("服务器ip:");
    	scanf("%s",SER_IP);
    	printf("服务器端口号:");
    	scanf("%hd",&SER_PORT);
    	printf("客户端ip:");
    	scanf("%s",CLI_IP);
    	printf("客户端口号:");
    	scanf("%hd",&CLI_PORT);
    
    
    
    
    	int cfd = socket(AF_INET,SOCK_DGRAM,0);
    	if(cfd == -1)
    	{
    		perror("socket error");
    		return -1;
    	}
    	//	printf("sock\n");
    
    	struct sockaddr_in cin;
    	cin.sin_family = AF_INET;
    	cin.sin_port = htons(CLI_PORT);
    	cin.sin_addr.s_addr = inet_addr(CLI_IP);
    	if(bind(cfd,(struct sockaddr*)&cin,sizeof(cin))==-1) 
    	{
    		perror("bind 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);
    	socklen_t s_socklen=sizeof(sin);       
    	char wbuf[128]="";
    	//数据包
    
    	msg_t msgbuf;
    	printf("请注册名字:\n");
    	scanf("%s",msgbuf.usrname);
    	char name[20]="";
    	strcpy(name,msgbuf.usrname);
    	while(getchar()!=10);
    	msgbuf.type = 'L';
    	sendto(cfd,&msgbuf,sizeof(msgbuf),0,(struct sockaddr*)&sin,sizeof(sin));
    
    //	bzero(msgbuf,sizeof(msgbuf));
    	recvfrom(cfd,&msgbuf,sizeof(msgbuf),0,(struct sockaddr*)&sin,&s_socklen);
    	//	printf("服务器的消息:%s\n",buf);
    	if(strcmp(msgbuf.msgtext,"success")==0)
    	{
    		struct pollfd pfds[2];
    
    		pfds[0].fd = 0;
    		pfds[0].events = POLLIN;
    
    		pfds[1].fd = cfd;
    		pfds[1].events = POLLIN;
    
    		while(1)
    		{
    			int res = poll(pfds , 2, -1);
    			if(res == 0)
    			{
    				printf("time out \n");
    				return -1;
    			}else if(res == -1)
    			{
    				perror("poll error");
    				return -1;
    			}
    
    			//程序执行至此,说明集合中有事件产生,接下来根据不同的事件,执行不同的函数即可
    			if(pfds[0].revents == POLLIN)    //判断是否为终端输入
    			{
    				//从终端获取数据
    				fgets(wbuf, sizeof(wbuf), stdin);
    				wbuf[strlen(wbuf)-1] = '\0';
    				if(strcmp(wbuf, "quit") == 0)
    				{
    					break;
    				}
    				msgbuf.type = 'C';
    				strcpy(msgbuf.usrname,name);
    				strcpy(msgbuf.msgtext,wbuf);
    
    				//讲数据发送给服务器
    				sendto(cfd,&msgbuf,sizeof(msgbuf),0,(struct sockaddr*)&sin,sizeof(sin));
    			}
    
    			//判断是否为服务器发来消息
    			if(pfds[1].revents == POLLIN)
    			{
    				//接收服务器发来的消息
    
    				recvfrom(cfd,&msgbuf,sizeof(msgbuf),0,(struct sockaddr*)&sin,&s_socklen);
    
    				if(msgbuf.type=='C')
    				{
    
    					printf("%s:%s\n",msgbuf.usrname,msgbuf.msgtext);
    				}
    			}
    
    		}
    
    	}
    
    
    	return 0;
    }
    

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值