1.实现功能

本代码主要实现了socket编程epoll模型实现多个客户端连接服务器,客户端可以进行群发消息和接收用户输入文本信息,然后发送该信息给服务器,服务器收到后发送应答信息。客户端接收并显示该应答信息,文章的后面会附上完整代码哦!

1.1

服务器使用epoll模型,支持多个客户端同时连接。

多个客户端同时连接

实现代码:

实现功能:客户端输入3333给服务器后服务器对客户端进行应答返回3333

实现代码

上线的客户端会存放到客户容器中,发送数据时会对这些客户端描述符都进行发送

实现功能:输入user会获取到所有的在线客户端的文件描述符

实现代码

实现功能:客户端输入exit或ctrl+c后退出该客户端

实现代码

输入事件判断如果没有接收到数据说明按下ctrl+c了,所以进行清除该文件描述符

输入exit也一致

客户端代码

#include<sys/types.h>
#include <sys/socket.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <pthread.h>
int socket_fd;
char buff[1024];
void* pthread_fun(void* arg)
{while (1){memset(buff, 0, 1024);fgets(buff, sizeof(buff), stdin);write(socket_fd, buff, strlen(buff));if (strncmp(buff, "exit", 4) == 0){break;}}
}
int main()
{int num;int count = 0;char buff1[1024];struct sockaddr_in server_addr;int clientlist[1024];int i = 0;bzero(&server_addr, sizeof(struct sockaddr_in));server_addr.sin_family = AF_INET;//IPV4server_addr.sin_port = htons(8888);inet_aton("127.0.0.1", &server_addr.sin_addr);socket_fd = socket(AF_INET, SOCK_STREAM, 0);if (socket_fd == -1){printf("socket error %s\n", strerror(errno));exit(-1);}if (connect(socket_fd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr)) == -1){printf("connect error %s\n", strerror(errno));exit(-1);}printf("connect success\n");pthread_t thread;int res;res = pthread_create(&thread, NULL, pthread_fun, NULL);if (res != 0){printf("pthread_create error:%s\n", strerror(res));}while (true){memset(buff,0,sizeof(buff));read(socket_fd,buff,sizeof(buff));if (strncmp(buff, "exit", 4) == 0){break;}else if (strncmp(buff, "user", 4) == 0){memset(buff1, 0, sizeof(buff1));count = 0;read(socket_fd, clientlist, sizeof(clientlist));printf("client list\n");for (i = 0; i < 1024; i++){if (clientlist[i] != 0){memset(buff1, 0, sizeof(buff1));count++;sprintf(buff1, "client%d", clientlist[i]);printf("%d:%s\n",count,buff1);}}//printf("client list\n");//for (i = 0; clientlist[i]; i++)//{//   memset(buff1, 0, sizeof(buff1));//  count++;//    sprintf(buff1, "client%d", clientlist[i]);//  printf("%d:%s\n",count,buff1);//}//for (map<int, string>::iterator it = client_map.begin(); it != client_map.end(); it++)//{//  memset(buff1, 0, sizeof(buff1));//  count++;//    //sprintf(buff1, "client%d", it->first);// printf("%d\n",count);//}}else{printf("%s\n", buff);}}close(socket_fd);return 0;
}

服务器代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <map>
#include <string>
using namespace std;
map<int, string> client_map;
int count = 0;
int clientlist[1024] = { 0 };
void handle_accept(int epollfd, int socket_fd);
int main()
{int i;int res;struct sockaddr_in server_addr;int socket_fd;socket_fd = socket(AF_INET, SOCK_STREAM, 0);if (socket_fd == -1){printf("socket error:%s", strerror(errno));exit(1);}//设置地址重用int opt;if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(opt)) < 0){perror("setsockopt\n");close(socket_fd);exit(1);}bzero(&server_addr, sizeof(struct sockaddr_in));server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = INADDR_ANY;server_addr.sin_port = htons(8888);res = bind(socket_fd, (const sockaddr*)&server_addr, sizeof(struct sockaddr_in));if (res == -1){printf("bind error:%s", strerror(errno));exit(1);}res = listen(socket_fd, 1024);if (res == -1){printf("listen error:%s", strerror(errno));exit(1);}//epoll流程int epollfd;int ret;epollfd = epoll_create(1500);struct epoll_event event;event.events = EPOLLIN;event.data.fd = socket_fd;//添加监听文件描述符事件epoll_ctl(epollfd, EPOLL_CTL_ADD, socket_fd, &event);int fd;while (1){struct epoll_event events[100];//查询就绪表 获取已经就绪的事件ret=epoll_wait(epollfd, events, 100, -1);printf("ret=%d\n", ret);for (i = 0; i < ret; i++){fd = events[i].data.fd;if ((fd == socket_fd) && (events[i].events & EPOLLIN)){handle_accept(epollfd, socket_fd);continue;}else if (events[i].events & EPOLLIN){int num;char buff[1024];char buff1[1024];//输入事件memset(buff, 0, sizeof(buff));memset(buff1, 0, sizeof(buff1));num=read(events[i].data.fd, buff, sizeof(buff));if (num <= 0){memset(&event, 0, sizeof(struct epoll_event));event.events = EPOLLIN;event.data.fd = events[i].data.fd;epoll_ctl(epollfd, EPOLL_CTL_DEL, events[i].data.fd, &event);close(events[i].data.fd);client_map.erase(events[i].data.fd);continue;}else{if (strncmp(buff,"exit",4) == 0){write(events[i].data.fd, buff, sizeof(buff));memset(&event, 0, sizeof(struct epoll_event));event.events = EPOLLIN;event.data.fd = events[i].data.fd;epoll_ctl(epollfd, EPOLL_CTL_DEL, events[i].data.fd, &event);close(events[i].data.fd);client_map.erase(events[i].data.fd);clientlist[events[i].data.fd-5] = 0;continue;}else if(strncmp(buff, "user", 4) == 0){//for (int i = 0; i < 1024; i++)//{// clientlist[i] = 0;//}write(events[i].data.fd, buff, sizeof(buff));i = 0;//for (map<int, string>::iterator it = client_map.begin(); it != client_map.end(); it++)//{//   clientlist[i] = it->first;//    i++;//    printf("i=%d\n", i);//}/*printf("it->first=%d\n", clientlist[0]);*/write(events[i].data.fd, clientlist , sizeof(clientlist));continue;}else{for (map<int, string>::iterator it = client_map.begin(); it != client_map.end(); it++){sprintf(buff1, "receive client%d content:%s", events[i].data.fd, buff);write(it->first, buff1, sizeof(buff1));}}}continue;}}}close(epollfd);close(socket_fd);return 0;
}
void handle_accept(int epollfd, int socket_fd)
{struct epoll_event ev;socklen_t len;struct sockaddr_in client_addr;int new_fd;len = sizeof(struct sockaddr);new_fd = accept(socket_fd, (struct sockaddr*)(&client_addr), &len);printf("1111\n");if (new_fd == -1){printf("accept error:%s", strerror(errno));exit(1);}else{printf("new_fd: %d IP:%s PORT %d\n", new_fd, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));//添加来自客户端的描述符和事件ev.data.fd = new_fd;ev.events = EPOLLIN;epoll_ctl(epollfd, EPOLL_CTL_ADD, new_fd, &ev);//添加到用户上线容器中char str[80];sprintf(str, "clinet%d", count);client_map.insert(pair<int,string>(new_fd,str));clientlist[count] = new_fd;count++;}
}

第一次写博客写的比较糟,如果大家对代码有问题的话可以在下面留言,我会及时进行回复的

linux socket编程epoll模型实现群发消息相关推荐

  1. linux线程同步 epoll,Linux网络编程--epoll 模型原理详解以及实例

    1.简介 Linux I/O多路复用技术在比较多的TCP网络服务器中有使用,即比较多的用到select函数.Linux 2.6内核中有提高网络I/O性能的新方法,即epoll . epoll是什么?按 ...

  2. socket编程 -- epoll模型服务端/客户端通信的实现

    https://blog.csdn.net/y396397735/article/details/50680359 本例实现如下功能: 支持多客户端与一个服务端进行通信,客户端给服务端发送字符串数据, ...

  3. 对于linux socket与epoll配合相关的一些心得记录

    对于linux socket与epoll配合相关的一些心得记录 没有多少高深的东西,全当记录,虽然简单,但是没有做过测试还是挺容易让人糊涂的 int nRecvBuf=32*1024;//设置为32K ...

  4. Linux Socket编程

    IP socket 是在其上建立高级Internet 协议的最低级的层:从HTTP到SSL到POP3到Kerberos再到UDP-Time,每种Internet协议都建立在它的基础上.为了实现自定义的 ...

  5. linux socket 编程

    socket  <script type="text/javascript"> </script> <script type="text/j ...

  6. Linux网络服务器epoll模型的socket通讯的实现(一)

    准备写一个网络游戏的服务器的通讯模块,参考网上看到的一些代码,在linux下面实现一个多线程的epoll模型的socket通讯的代码,以下是第一部分多线程的切换代码: 1 #include <s ...

  7. 【Linux Socket 编程入门】05 - 拉个骡子溜溜:TCP编程模型代码分析

    (一) 看看以前学了啥 前面介绍了socket的分类,IP地址,端口号(port),常用的socket数据结构以及常用的函数.现在我们来看一个例子,看看socket编程究竟是什么. (二) 一图看懂客 ...

  8. 网络编程——epoll模型编程

    文章目录 目的 内容 代码及测试结果 (1) 使用条件触发方式实现回声服务器端(及客户端): (2) 使用边缘触发方式实现回声服务器端(及客户端): (3) 实现聊天服务器端,使其可以在连接到服务器端 ...

  9. linux下编程epoll实现将GPS定位信息上报到服务器

    操作系统:CentOS 开发板:fl2440 开发模块:A7(GPS/GPRS),RT3070(无线网卡) ********************************************** ...

最新文章

  1. Ubuntu18.04 编译 ncnn
  2. 真人语音朗读软件_才知道,手机还自带文字转语音功能,一键按下便可实现,网友:赞...
  3. 11.python并发入门(part4 死锁与递归锁)
  4. ubuntu设置jupyter
  5. php+nginx环境配置注意事项
  6. 利用CSS按比例缩小图片
  7. Q85:对比“直接光照”和“间接光照”的反射模型
  8. 《数学之美》—余弦定理和新闻的分类
  9. PostgreSQL(1)数据库安装(win和linux)
  10. iOS网络开发—POST请求和GET请求
  11. 有关Lattice Diamond的若干bug
  12. 卸载重装Netmeeting
  13. python 标准库库
  14. php 与 html 的混合编程
  15. 读《Boost程序库完全开发指南》
  16. 微信h5获取用户地址信息
  17. apk解包工具 安卓_MT管理器最新2.9.3版支持ROOT后安卓10安卓11文件修改替换
  18. Python:python镜像源汇总及使用
  19. JAVA毕业设计服装连锁店后台管理系统计算机源码+lw文档+系统+调试部署+数据库
  20. iOS如何转让 App 给公司或个人

热门文章

  1. 我的世界服务器修改logo,《我的世界》服务器创始人因病去世 玩家建致敬标志...
  2. 人工智能、机器学习、数据挖掘等基础概念-考研复试面试
  3. Windows系统中Redis 下载安装
  4. arcgis软件的问题
  5. Java实训步骤第一天
  6. 厉害了!竟然有程序员在GitHub上建了一个新华词典数据库
  7. 聊聊前端工程化的实践与未来
  8. python练习题:使用循环完成剪刀石头布游戏,提示用户输入要出的拳 :石头(1)/剪刀(2)/布(3)/退出(4)电脑随机出拳比较胜负,显示用户胜、负还是平局
  9. android 进度条图标方形_android 进度条的样式
  10. CCTV又双叒叕来ThinkSNS,究竟为哪般?