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

2023.7.30(epoll实现并发服务器)

服务器

#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <sys/types.h> 
#include <unistd.h>
#define ERR(msg)                                       	   \do {                                                   \printf("%s %s %d:", __FILE__, __func__, __LINE__); \perror(msg);                                       \exit(-1);                                          \} while (0)
//端口号的网络字节序 1024~49151
#define PORT 6666 //设置端口号6666
#define IP "192.168.250.100"//设置本机IP
#define N 32
int main(int argc, char* argv[])
{// 1.创建红黑树int epfd = epoll_create(1);if (epfd < 0) {ERR("epfd err");}// 2.创建套接字int socketfd;if (-1 == (socketfd = socket(AF_INET, SOCK_STREAM, 0))) {ERR("socket error");}// 3.struct epoll_event eventstruct epoll_event event;event.events = EPOLLIN | EPOLLET;event.data.fd = socketfd;if (epoll_ctl(epfd, EPOLL_CTL_ADD, socketfd, &event) < 0) {ERR("epoll_ctl error");}// 填充服务器地址struct sockaddr_in serveraddr, clientaddr;serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(PORT);serveraddr.sin_addr.s_addr = inet_addr(IP);socklen_t serveraddr_len = sizeof(serveraddr);socklen_t clientaddr_len = sizeof(clientaddr_len);// 绑定if (bind(socketfd, (struct sockaddr*)&serveraddr, serveraddr_len) < 0) {ERR("bind error");}// 监听if (listen(socketfd, 10) < 0) {ERR("listen errorG");}int acceptfd, ret, i;int bytes;struct epoll_event events[20];char buf[N] = {0};while (1) {//使用epoll_wait 检测文件描述符是否发生ret = epoll_wait(epfd, events, 20, -1);if (ret > 0) {for (i = 0; i < ret; i++) {// 判断文件描述符数量if (events[i].data.fd == socketfd) {// 判断对应文件描述符的IO类型if (events[i].events & EPOLLIN) {acceptfd = accept(events[i].data.fd, (struct sockaddr*)&clientaddr, &clientaddr_len);if (acceptfd < 0) {ERR("accept error");}printf("IP:%s 连接成功\n", (char*)inet_ntoa(clientaddr.sin_addr));// 将新客户端通信套接字挂到树上struct epoll_event event;event.events = EPOLLIN | EPOLLET;event.data.fd = acceptfd;if (epoll_ctl(epfd, EPOLL_CTL_ADD, acceptfd, &event) < 0) {ERR("epoll_ctl err");}}} else {// 处理客户端信息if (EPOLLIN & events[i].events == EPOLLIN) {memset(buf, 0, sizeof(buf));if (-1 == (bytes = recv(events[i].data.fd, buf, sizeof(buf), 0))) {ERR("recv error");} else if (bytes == 0) {// 客户端断开信息printf("acceptfd:%d 断开连接\n", events[i].data.fd);// 关闭对应文件描述符close(events[i].data.fd);// 实现对于epoll的控制epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, NULL);}else {printf("buf:%s\n", buf);}if (-1 == send(events[i].data.fd, buf, N, 0)) {ERR("send error");}}}}} else {ERR("epoll_wait error");}}close(socketfd);return 0;

客户端

#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>#define ERR(msg)                                        \do {                                                   \printf("%s %s %d:", __FILE__, __func__, __LINE__); \perror(msg);                                       \exit(-1);                                          \} while (0)#define N 32
//端口号网络字节序
#define PORT 6666   
#define IP "192.168.250.100"
int main(int argc, const char* argv[])
{// 1.创建套接字int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (-1 == sockfd) {ERR("socket error");}// 2.填充服务器网络信息结构体struct sockaddr_in serveraddr;memset(&serveraddr, 0, sizeof(serveraddr));serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(PORT);serveraddr.sin_addr.s_addr = inet_addr(IP);socklen_t serveraddr_len = sizeof(serveraddr);char buf[N] = {0};int res = 0;// 3.尝试与服务器建立连接if (-1 == connect(sockfd, (struct sockaddr*)&serveraddr, serveraddr_len)) {ERR("connect error");}printf("与服务器建立连接成功..\n");while (1) {memset(buf, 0, sizeof(buf));fgets(buf, N, stdin);buf[strlen(buf) - 1] = '\0'; //清理结尾的\n//发送数据if (-1 == send(sockfd, buf, sizeof(buf), 0)) {ERR("send error");}//接收服务器的应答信息if (-1 == (res = recv(sockfd, buf, sizeof(buf), 0))) {ERR("recv error");}if (0 == res) {break;}//输出应答信息printf("应答为:[%s]\n", buf);}//关闭套接字close(sockfd);return 0;}

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

相关文章:

  • 小研究 - 基于解析树的 Java Web 灰盒模糊测试(一)
  • SpringBoot接手JSP项目--【JSB项目实战】
  • Python模块psycopg2连接postgresql
  • Kotlin基础(八):泛型
  • Java学习笔记——(10)环境变量path配置及其作用
  • 【图像去噪】基于进化算法——自组织迁移算法(SOMA)的图像去噪研究(Matlab代码实现)
  • TMS WEB Core Crack,TMS软件Delphi组件RADical Web
  • PHP使用Redis实战实录4:单例模式和面向过程操作redis的语法
  • 解决:移动端H5的<video>初始化拿不到总时长
  • 百度云上传身份证获取身份信息封装
  • vscode 上cmake 版本过低
  • OS-08-事件驱动:C10M是如何实现的?
  • mysql 主从同步排查和处理 Slave_IO、Slave_SQL
  • 基于解析法和遗传算法相结合的配电网多台分布式电源降损配置(Matlab实现)
  • 07mysql查询语句之子查询
  • 笙默考试管理系统-MyExamTest(22)
  • Windows 不同方式打开的cmd/dos窗口属性配置不同
  • 性能优化-webpack配置gzip
  • RabbitMQ 教程 | 第3章 客户端开发向导
  • 基于深度学习的CCPD车牌检测系统(PyTorch+Pyside6+YOLOv5模型)
  • input元素中的form属性有什么用?
  • 【数据结构篇C++实现】- 特殊的线性表 - 串
  • DevOps系列文章 之 Springboot单元测试
  • 04 linux之C 语言高级编程
  • 深入学习 Redis - Stream、Geospatial、HyperLogLog、Bitmap、Bitfields 类型扩展
  • Windows11+Opencv+Clion编译源码
  • 【机器学习】Cost Function
  • 【黑马头条之内容安全第三方接口】
  • 回归预测 | MATLAB实现GRNN广义回归神经网络多输入单输出回归预测(多指标,多图)
  • STM32 HAL库函数——HAL_UART_RxCpltCallback()详解