5.11作业

 server.c

#include <iohead.h>
#define MAX_CLIENTS 100
/*typedef struct
{
	int sockid;//客户端的套接字
	int id;//服务器给客户端分配id;
}Client;

Client clients[MAX_CLIENTS];//客户端数组
int next_id = 1;

//为客户端分配id
int add_clientid(int sockfd)
{
	if(next_id>MAX_CLIENTS)
	{
		printf("分配失败\n");
		return -1;
	}
	clients[next_id].sockid = sockfd;
	clients[next_id].id = next_id;

	return next_id++;
}*/
//讲一个拥有(描述符,监视方式,激活形式)的结构体变量fd,存放在监视列表arr中,并且监视列表的长度len自增1
void insert_fd(struct pollfd* arr,struct pollfd newfd,int* len)
{
	arr[*len] = newfd;
	(*len)++;
}
//将想要删除的描述符fd,从监视列表Arr中删除,并且监视列表长度len自减1
void remove_fd(struct pollfd* arr,int fd,int* len)
{
	int i;
	for(i=0;i<*len;i++)
	{
		if(arr[i].fd == fd)
		{
			int j=0;
			for(j=i;j<*len-1;j++)
			{
				arr[j]=arr[j+1];
			}
			//arr[j]=-1;//将删除空出来的一个位置,变成非法描述符,不变也可以

		}
	}
	(*len)--;
}
int main(int argc, const char *argv[])
{

	if(argc<2){
		printf("请输入端口号\n");
		return 1;
	}
	short port = atoi(argv[1]); // argv[1] = "8888" -> 00111000 00111000 00111000 00111000 
							//int a = 8888 ->        00000000 00000000 00100010 10111000
	//printf("port = %d\n",port);
	int client_arr[10] = {0};//用来存放所有客户端套接字的数组
	int client_count = 0;//记录客户端套接字的数量

	int server = socket(AF_INET,SOCK_STREAM,0);

	struct sockaddr_in addr = {0};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = inet_addr("0.0.0.0");

	if(bind(server,(struct sockaddr*)&addr,sizeof(addr)) == -1){
		perror("bind");
		return 1;
	}

	listen(server,10);

	//准备一个poll监视列表(同时也是激活列表)
	struct pollfd list[10]={0};
	int list_len = 0;//用来记录监视列表中描述符的数量

	//先准备想要监视的描述符,注意将描述符联通监视形式,存入结构体中,应为监视列表是这个结构体形式的数组
	struct pollfd poll_server = {fd:server,events:POLLIN,revents:0};
	struct pollfd poll_stdin = {fd:0,events:POLLIN,revents:0};

	//将想要监视的描述符,存放监视列表list中:server,0
	insert_fd(list,poll_server,&list_len);
	insert_fd(list,poll_stdin,&list_len);

	while(1)
	{
		poll(list,list_len,-1);
		for(int i=0;i<list_len;i++)
		{
			int fd = list[i].fd;
			if(list[i].revents == POLLIN)
			{
				//说明list[i].fd被激活了
				if(fd==server)
				{
					//如果激活的是服务器
					printf("有新客户端链接\n");
					int client = accept(server,NULL,NULL);
					//记得将新链接的客户端加入监视列表中
					struct pollfd poll_client={fd:client,events:POLLIN,revents:0};
					insert_fd(list,poll_client,&list_len);
					//add_clientid(client);
					continue;
				}
				if(fd == 0)
				{
					//如果激活的是标准输入流
					char buf[1024]="";
					scanf("%1023s",buf);
					getchar();
					printf("键盘输入的数据:%s\n",buf);
					continue;
				}
				char buf[64]="";
				int res=read(fd,buf,64);
				if(res==0)
				{
					printf("客户端断开\n");
					remove_fd(list,fd,&list_len);
					close(fd);
				}
				else
				{
					for(int j=0;j<list_len;j++)
					{
						if(list[j].fd==server){continue;}
						if(list[j].fd==0){continue;}
						if(list[j].fd!=list[i].fd)
						{
							int res1=send(list[j].fd,buf,strlen(buf)+1,0);
							if(res1<=0)
							{
								printf("客户端之间连接失败\n");
								break;
							}
						}
					}
				}
			}
		}
	}
	return 0;

}

client1.c

#include <iohead.h>
int main(int argc, const char *argv[])
{
    if(argc<2)
	{
		printf("请输入端口号\n");
		return 1;
	}
	int port = atoi(argv[1]);
	
	int client = socket(AF_INET,SOCK_STREAM,0);
	
	struct sockaddr_in addr = {0};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = inet_addr("192.168.220.128");
	

	if(connect(client,(struct sockaddr*)&addr,sizeof(addr))==-1)
	{
		perror("bind");
		return 1;
	}

	//准备一个select监视列表;
	fd_set list;
	//初始化
	FD_ZERO(&list);

	//将想要监视的描述符,添加进入监视列表list中:server,0
	FD_SET(client,&list);
	FD_SET(0,&list);
	int max=4;
	while(1)
	{
		fd_set temp = list;
		select(max,&temp,NULL,NULL,NULL);
		//判断摸个描述符是否在监视列表里面
		if(FD_ISSET(client,&temp))
		{
		//	printf("将client传送给服务器\n");
			char buf[64]={0};
			int res = recv(client,buf,sizeof(buf),0);
			if(res<=0)
			{
				printf("客户端断开\n");
				break;
			}
			printf("收到消息%s\n",buf);
		}
		if(FD_ISSET(0,&temp))
		{
			printf("将消息发送给服务器\n");
			char buf[64]={0};
			//printf("请输入:");
			scanf("%s",buf);
			getchar();
			fflush(stdout);
			int res1 = send(client,buf,strlen(buf)+1,0);
			if(res1<=0)
			{
				printf("服务器断开\n");
				break;
			}
		//	printf("发送消息%s\n",buf);
		}

	}
	close(client);
	return 0;
}

client2

#include <iohead.h>
/*typedef struct
{
	int client_id;
	volatile int *running;
}threadarg;*/

void* thread_main(void* arg)
{
	int client=*(int*)arg;
	while(1)
	{
		char buf[64]={0};
		int res1 = recv(client,buf,sizeof(buf),0);
		if(res1<=0)
		{
			printf("连接失败\n");
			break;
		}
		printf("服务端发来消息%s\n",buf);
	}
	return NULL;
}
int main(int argc, const char *argv[])
{
    if(argc<2)
	{
		printf("请输入端口号\n");
		return 1;
	}
	int port = atoi(argv[1]);
	
	int client = socket(AF_INET,SOCK_STREAM,0);
	
	struct sockaddr_in addr = {0};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = inet_addr("192.168.220.128");
	

	if(connect(client,(struct sockaddr*)&addr,sizeof(addr))==-1)
	{
		perror("bind");
		return 1;
	}

	/*volatile int running=1;
	threadarg *arg=malloc(sizeof(threadarg));
	arg->client_id=client;
	arg->running=&running;*/


		//创建子进程
		pthread_t id=0;
		pthread_create(&id,NULL,thread_main,&client);
		pthread_detach(id);

	while(1)
	{
		//printf("请输入:");
		char buf[64]={0};
		scanf("%s",buf);
		getchar();
		fflush(stdout);
		int res = send(client,buf,strlen(buf)+1,0);
		if(res<=0)
		{
			//running = 0;
			break;
		}
		printf("已经发送%s\n",buf);
	}
	close(client);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值