4.21作业

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/wait.h>
#include <semaphore.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/times.h>
#include <sys/select.h>
#include <sqlite3.h>
#include <poll.h> 

int main(int argc, const char *argv[])
{
	//创建套接字
	int sfd = socket(AF_INET,SOCK_DGRAM,0);
	if(sfd == -1)
	{
		perror("socket error");
		return -1;
	}
	printf("套接字创建成功!  sfd = %d\n",sfd);
	//端口号快速重用
	int reuse = -1;
	if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1)
	{
		perror("setsockopt error");
		return -1;
	}
	printf("端口号快速重用成功! \n");
	//绑定
	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;
	}
	printf("绑定成功\n");
	//数据收发
	struct sockaddr_in cin;
	socklen_t socklen = sizeof(cin);

	//创建一个用于检测文件描述符的容器
	struct pollfd pfds[2];
	pfds[0].fd = sfd;  //表示第一个元素检测0号文件描述符
	pfds[0].events = POLLIN;   //要检测0号文件描述符的读事件
	pfds[1].fd = 0;          //表示第一个元素检测0号文件描述符
	pfds[1].events = POLLIN;  //要检测0号文件描述符的读事件
	int res = -1;
	struct usr usr_arr[1024] = {0};
	struct cli_msg cli;
	char wbuf[128]="";
	char buf[128]="";
	int i = 0;
	while(1)
	{
		res = poll(pfds,2,-1);    //阻塞检测文件描述符集合中是否有事件产生
		if( res == 0)
		{
			printf("time out\n");
			return -1;
		}else if(res == -1)
		{
			perror("poll error");
			return -1;
		}
jixu:	
		//读事件
		if(pfds[0].revents == POLLIN)
		{
			recvfrom(sfd,(struct cli_msg*)&cli,sizeof(cli),0,(struct sockaddr*)&cin,&socklen);

			//判断消息类型
			if(cli.type == 1)
			{
				int k=0;
				int a=1;
				//遍历数组将消息判断用户是否重复并发回判断结果
				while(k<i)
				{
					if(strcmp(usr_arr[k].usrname,cli.usrname)==0)
					{
						strcpy(buf,"1");
						sendto(sfd,&buf,sizeof(buf),0,(struct sockaddr*)&cin,sizeof(cin));
						goto jixu;
					}else
					{
						k++;
					}
				}
				strcpy(buf,"2");
				sendto(sfd,&buf,sizeof(buf),0,(struct sockaddr*)&cin,sizeof(cin));
 
				//客户端ID和地址信息存入
				strcpy(usr_arr[i].usrname,cli.usrname);
				usr_arr[i].cin = cin;
				printf("--------------------%s已上线--------------------\n",usr_arr[i].usrname);
				i+=1;
			}
 
			else if(cli.type == 2)
			{
				int l = 0;
				int a ;
				printf("%s:%s\n",cli.usrname,cli.msgText);
 
				if(strcmp(cli.msgText,"quit")==0)
				{
					for(l=0;l<i;l++)
					{
						if(cin.sin_port == usr_arr[l].cin.sin_port)
						{
							printf("--------------------%s已下线--------------------\n",usr_arr[l].usrname);
							for(a=l;a<i;a++)
							{
								usr_arr[a]=usr_arr[a+1];
							}
							i--;
							goto jixu;
 
						}
					}
				}
				for(int j=0;j<i;j++)
				{
					//遍历数组将消息发给其他客户端
					if(usr_arr[j].cin.sin_port != cin.sin_port)
					{
						sendto(sfd,&cli,sizeof(cli),0,(struct sockaddr*)&(usr_arr[j].cin),sizeof(usr_arr[j].cin));
						perror("sendto");
					}
				}
 
			}
 
		}
 
 
 
		//写事件
		if(pfds[1].revents == POLLIN )
		{       
				   memset(cli.msgText,0,sizeof(cli.msgText));
 
				   fgets(cli.msgText,sizeof(cli.msgText),stdin);
				   cli.msgText[strlen(cli.msgText)-1]=0;
				   cli.type = 3;
               for(int c=0;c<i;c++)
			   {
				   sendto(sfd,&cli,sizeof(cli),0,(struct sockaddr*)&(usr_arr[c].cin),sizeof(usr_arr[c].cin));
				   perror("sento");
			   }
 
		}
	}
 
	close(sfd);

	return 0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/wait.h>
#include <semaphore.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/times.h>
#include <sys/select.h>
#include <sqlite3.h>

int main(int argc, const char *argv[])
{
	//创建套接字
	int cfd = socket(AF_INET,SOCK_DGRAM,0);
	if(cfd == -1)
	{
		perror("socket error");
		return -1;
	}
	//printf("套接字创建成功!  cfd = %d\n",cfd);
	//端口号快速重用
	int reuse = -1 ;
	if(setsockopt(cfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1)
	{
		perror("setsockopt error");
		return -1;
	}
	//printf("端口快速重用成功!\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;
	  }
	  printf("绑定成功!\n");*/
	//数据收发
	struct sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(atoi(argv[2]));
	sin.sin_addr.s_addr = inet_addr(argv[1]);
 
 
	//创建一个用于检测文件描述符的容器
	struct pollfd pfds[2];
	pfds[0].fd = cfd;          //表示第一个元素检测0号文件描述符
	pfds[0].events = POLLIN;   //要检测0号文件描述符的读事件
	pfds[1].fd = 0;          //表示第一个元素检测0号文件描述符
	pfds[1].events = POLLIN;   //要检测0号文件描述符的读事件
	int res=-1;
	struct usr usr_arr[1024]={0};
	struct cli_msg cli;
	struct cli_msg cli1;
	char buf[128]="";
	int i=0;
 
	while(1)
	{
		//登陆后输入ID并存入信息结构体中
		printf("\033[01;33;10m请输入ID:\033[0m");
		scanf("%s",cli.usrname);
		//printf("%s\n",cli.usrname);
		cli.type = 1;
 
		//向服务器发送ID和地址信息
		sendto(cfd,&cli,sizeof(cli),0,(struct sockaddr*)&sin,sizeof(sin));
 
		//服务器判断ID是否存在后返回结果
		recvfrom(cfd,&buf,sizeof(buf),0,NULL,NULL);
 
		if(strcmp(buf,"1")==0)
		{
			printf("\033[01;31;10m用户名重复!请重新输入!\033[0m\n");
 
		}else
		{
			break;
		}
	}
 
	while(1)
	{
 
		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)
		{ 
			recvfrom(cfd,&cli1,sizeof(cli1),0,NULL,NULL);
			if(cli1.type ==2)
			{
			printf("\033[01;32;10m%s:\033[0m%s\n",cli1.usrname,cli1.msgText);
			}else if(cli1.type == 3)
			{
				printf("\033[01;31;10m>>>>>>>>>>系统提示:%s<<<<<<<<<<\033[0m\n",cli1.msgText);
 
			}
		}
 
 
		//写事件
		if(pfds[1].revents == POLLIN )
		{
			//memset(cli.msgText,0,sizeof(cli.msgText));
			fgets(cli.msgText,sizeof(cli.msgText),stdin);
			cli.msgText[strlen(cli.msgText)-1]=0;
			cli.type = 2;
			sendto(cfd,(struct cli_msg*)&cli,sizeof(cli),0,(struct sockaddr*)&sin,sizeof(sin));
			//printf("%s\n",cli.msgText);
 
		}
	}
 
	close(cfd);

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值