当前位置: 首页 > news >正文

7月14日作业

一、实现2个客户端之间互相聊天

        要求:服务器使用 select 模型实现接受多个客户端连接,以及转发消息 客户端要求:使用 poll 模型解决 技能够 read 读取服务器发来的消息,又能够scanf读取键盘输入的信息 客户端服务器不允许开启额外线程和进程

服务端代码

#include <25041head.h>
struct Client
{int fd;  //发送者id端口号int id;  //接收者端口号char mtext[1024];  //发送的消息内容
};
struct Client_arr
{int fd;int id;
};void insert_client(struct Client_arr *client_arr,int *client_arr_len,int newclient)
{client_arr[*client_arr_len].fd=newclient;client_arr[*client_arr_len].id=*(client_arr_len);(*client_arr_len)++;
}void rm_client(struct Client_arr *client_arr,int *client_arr_len,int client)
{int i=0,j=0;for(i=0;i<*client_arr_len;i++){			struct Client new_client;if(client_arr[i].fd==client)break;}for(j=i;j<*client_arr_len-1;j++){client_arr[j]=client_arr[j+1];}(*client_arr_len)--;
}int main(int argc, const char *argv[])
{if(argc<2){printf("请输入端口号!\n");return 1;}short port=atoi(argv[1]);//创建服务器套接字int server=socket(AF_INET,SOCK_STREAM,0);//准备好要写入的套接字信息结构体,初始化信息struct sockaddr_in addr={0};//设置地址族为ipv4addr.sin_family=AF_INET;//设置监听端口号addr.sin_port=htons(port);//设定接收的ip地址,0为接收所有addr.sin_addr.s_addr=inet_addr("0.0.0.0");//将结构体信息(ip和port)写入套接字中if(bind(server,(struct sockaddr*)&addr,sizeof(addr))==-1){perror("bind error..");return -1;}//监听listen(server,10);fd_set list;  //创建监视列表FD_ZERO(&list);  //初始化信息FD_SET(server,&list);  //服务器写入监视列表中FD_SET(0,&list);  //监视输入流int fd_count=3;//申请数组存客户端套接字struct Client client_msg={0};struct Client_arr client_arr[100]={0};int client_arr_len=0;while(1){//备份监视列表,select激活列表和监视列表是同一张fd_set backup=list;	int fd;select(fd_count+1,&backup,NULL,NULL,NULL);  //list是监视列表,backup是激活列表if(FD_ISSET(server,&backup)){//接收//准备好客户端结构体struct sockaddr_in client_addr;int client_len = sizeof(client_addr);//接收客户端,返回客户端套接字int client = accept(server,(struct sockaddr*)&client_addr,&client_len);if(client==-1){ERRLOG("客户端接受失败");}printf("有客户端连接成功!  ip=%s   port=%d\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));if(client>fd_count)fd_count=client;//监视新客户端套接字,加入监视列表中FD_SET(client,&list);//将套接字加入数组中insert_client(client_arr,&client_arr_len,client);}if(FD_ISSET(0,&backup)){char buf[128]="";scanf("%s",buf);getchar();printf("键盘输入数据:%s\n",buf);}//某客户端激活,调用该客户端套接字读,遍历for(int i=0;i<client_arr_len;i++){int client=client_arr[i].fd;if(FD_ISSET(client,&backup)){struct Client client_t;int res=read(client,&client_t,sizeof(struct Client));if(res==0){printf("客户端断开连接!\n");FD_CLR(client,&list);   //监视列表移除该客户端rm_client(client_arr,&client_arr_len,client);   //数组中删除该客户端continue;}//转发消息printf("客户端发来消息:%s\n",client_t.mtext);for(int i=0;i<client_arr_len;i++){if(client_t.id == client_arr[i].id && client_arr[i].fd != client){write(client_arr[i].fd,&client_t,sizeof(struct Client));continue;}}}}}close(server);return 0;
}

客户端代码

#include <25041head.h>
struct Client
{int fd;  //发送者id端口号int id;  //接收者端口号char mtext[1024];  //发送的消息内容
};int main(int argc, const char *argv[])
{if(argc<2){printf("请输入端口号!\n");return 1;}short 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("127.0.0.1");int a=connect(client,(struct sockaddr*)&addr,sizeof(addr));if(a==-1){printf("连接失败\n");return 0;}printf("链接成功\n");struct pollfd fds[2];// 初始化第一个元素(标准输入)fds[0].fd = 0;fds[0].events = POLLIN | POLLOUT;fds[0].revents = 0;// 初始化第二个元素(客户端套接字)fds[1].fd = client;fds[1].events = POLLIN;fds[1].revents = 0;while(1){poll(fds,2,-1);if(fds[0].revents & POLLOUT){printf("请输入接收消息客户端的id:");fflush(stdout);fds[0].events=POLLIN;continue;}if(fds[0].revents & POLLIN){int id_t;char mtext_t[128]="";scanf("%d",&id_t);printf("请输入发送的消息内容:");scanf("%s",mtext_t);getchar();struct Client client_msg={.fd=client,.id=id_t};strcpy(client_msg.mtext,mtext_t);write(client,&client_msg,sizeof(struct Client));fds[0].events=POLLIN|POLLOUT;}if(fds[1].revents & POLLIN)  // 接收消息{struct Client rev_msg;int res=read(client,&rev_msg,sizeof(struct Client));if(res==0){printf("客户端已断开\n");break;}printf("接收到来自客户端id为:%d 的消息:%s\n",rev_msg.id,rev_msg.mtext);continue;}}close(client);    return 0;
}

运行结果

http://www.lryc.cn/news/588323.html

相关文章:

  • 选择一个系统作为主数据源的优势与考量
  • 【数据结构】基于顺序表的通讯录实现
  • Hello, Tauri!
  • The Network Link Layer: WSNs 泛洪和DSR动态源路由协议
  • Python:打造你的HTTP应用帝国
  • 院级医疗AI管理流程—基于数据共享、算法开发与工具链治理的系统化框架
  • VScode链接服务器一直卡在下载vscode服务器/scp上传服务器,无法连接成功
  • Fiddler——抓取https接口配置
  • linux服务器换ip后客户端无法从服务器下载数据到本地问题处理
  • TextIn:文档全能助手,让学习效率飙升的良心软件~
  • Git commit message
  • 2.逻辑回归、Softmax回归
  • 数据驱动 AI赋能|西安理工大学美林数据“数据分析项目实战特训营”圆满收官!
  • # 电脑待机后出现死机不能唤醒怎么解决?
  • 基于HarmonyOS的智能灯光控制系统设计:从定时触发到动作联动全流程实战
  • 天地图前端实现geoJson与wkt格式互转
  • Java图片处理实战:如何优雅地实现上传照片智能压缩
  • 1688商品详情接口逆向分析与多语言SDK封装实践
  • Redis高可用集群一主从复制概述
  • Spring Boot Cucumber 测试报告嵌入方法
  • S7-1200 中 AT 覆盖参数的应用:灵活访问数据区域的实用指南
  • STM32小实验1--点亮LED
  • 【HarmonyOS】元服务概念详解
  • 学习日志09 python
  • 若依(RuoYi)框架项目结构全解析
  • 注解@Autowired和@Resource的区别
  • USB读写自动化压力测试
  • 【React Native】ScrollView 和 FlatList 组件
  • C++中STL六大组件List的简单介绍
  • UI前端大数据处理新挑战:如何高效处理实时数据流?