Linux-c TCP服务模型

1、TCP模型,服务端与客户端的搭建时序图

2、TCP模型,在创建阶段和通信阶段,对套接字的理解

2.1、tcp连接阶段

2.2、tcp通信状态

一个服务端与多个客户端的通信状态

TCP与UDP的对比

(下图是笔者理解所画,可能也许有错,欢迎指出)

3、基于EPOLL多路复用模型,代码实现的TCP服务端和客户端

3.1、EPOLL的几个主要的函数

3.1.1、epoll_create1(int flags)

创建epfd,笔者理解,这个是管理众多事件的一个集合。

3.1.2、epoll_ctl

用于添加和删除fd及其关联的事件

3.1.3、epoll_wait

阻塞等待监听的fd的时间发生变化

3.2、服务端代码(TCP+EPOLL)

#define BACKLOG 50  //支持多少个客户端连接int main(int argc, const char *argv[])
{//socketint server=socket(AF_INET, SOCK_STREAM, 0);if(server == -1){perror("socket error");return -1;}//bindstruct sockaddr_in serverAddr;serverAddr.sin_family=AF_INET;serverAddr.sin_port=htons(atoi(argv[1]));serverAddr.sin_addr.s_addr=inet_addr("0.0.0.0");if(bind(server,(struct sockaddr*)&serverAddr, sizeof(serverAddr))==-1){perror("bind server error");return -1;}//listenif(listen(server, BACKLOG)==-1){perror("listen error");return -1;}//epoll_createint epfd=epoll_create1(EPOLL_CLOEXEC);if(epfd==-1){perror("epoll_create1 error");return -1;}//epoll_ctl add/delstruct epoll_event e1;e1.data.fd=server;e1.events=EPOLLIN;if(epoll_ctl(epfd, EPOLL_CTL_ADD, server, &e1)==-1){//server文件FDperror("epoll_ctl add 1: error");return -1;}struct epoll_event e2;e2.data.fd=0;e2.events=EPOLLIN;if(epoll_ctl(epfd, EPOLL_CTL_ADD, 0, &e2)==-1){//标准输入perror("epoll_ctl add 2:error");return -1;}while(1){//epoll_waitstruct epoll_event eArr[50];int num=epoll_wait(epfd, eArr,50,-1);//printf("num=[%d]\n", num);//if(num >= 2){//	printf("num=[%d]!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n", num);//}if(num == -1){perror("epoll_wait error");return -1;}for(int i=0;i<num;i++){int fd=eArr[i].data.fd;int events=eArr[i].events;//以下由于只监听了EPOLLIN,因此不对事件进行判断if(fd==server){//服务端监听套接字struct sockaddr_in clientAddr;socklen_t clientAddrLen;int fd=accept(server, (struct sockaddr*)&clientAddr, &clientAddrLen);printf("有新的客户端连接[%s]:[%d],FD=[%d]\n",inet_ntoa(clientAddr.sin_addr),ntohs(clientAddr.sin_port),fd);//将此客户端fd添加到epfd中struct epoll_event e3;e3.data.fd=fd;e3.events=EPOLLIN;if(epoll_ctl(epfd,EPOLL_CTL_ADD,fd, &e3)==-1){perror("epoll_ctl add 3 error");return -1;}continue;}if(fd==0){//标准输入流printf("请输入:");char buf[64];fgets(buf,sizeof(buf), stdin);buf[strlen(buf)-1]=0;printf("键盘键入了:%s\n", buf);continue;}//客户端char buf[64]={0};struct sockaddr_in clientAddr;socklen_t clientAddrLen;ssize_t cnt=recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr*)&clientAddr, &clientAddrLen);printf("<<收到来自[%s]:[%d]的消息:\n[%ld]:%s\n",inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port),cnt,buf);if(cnt == 0){printf("<<客户端[%s]:[%d]的断开了连接:\n",inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));//从epfd中删除这个fdepoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL);continue;}//TODO 转换成大写,返还给客户端for(int j=0;j<cnt;j++){buf[j]=toupper(buf[j]);}cnt=send(fd, buf, sizeof(buf), 0);printf(">>向[%s]:[%d]发送了消息:\n[%ld]:%s\n",inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port),cnt,buf);}}return 0;
}

3.3、客户端代码(TCP+EPOLL)

int main(int argc, const char *argv[])
{//tcp epoll客户端//socketint client=socket(AF_INET, SOCK_STREAM, 0);if(client == -1){perror("socket error");return -1;}//connectstruct sockaddr_in serverAddr;serverAddr.sin_family=AF_INET;serverAddr.sin_port=htons(atoi(argv[1]));serverAddr.sin_addr.s_addr=inet_addr("127.0.0.1");if(connect(client, (struct sockaddr*)&serverAddr,sizeof(serverAddr))==-1){perror("connect error");return -1;}printf("与服务端成功创建连接\n");//epoll createint epfd=epoll_create1(EPOLL_CLOEXEC);if(epfd == -1){perror("epoll_create1 error");return -1;}//epoll ctl addstruct epoll_event e1;e1.data.fd=client;//将客户端fd,收到消息事件,添加e1.events=EPOLLIN;if(epoll_ctl(epfd, EPOLL_CTL_ADD, client, &e1)==-1){perror("epoll_ctl error [1]");return -1;}//添加事件:键盘输入//struct epoll_event e1;e1.data.fd=0;//将客户端fd,收到消息事件,添加e1.events=EPOLLIN;if(epoll_ctl(epfd, EPOLL_CTL_ADD, 0, &e1)==-1){perror("epoll_ctl error [1]");return -1;}while(1){struct epoll_event eArr[2];int num=epoll_wait(epfd, eArr, 2, -1);if(num == -1){perror("epoll_wait error");return -1;}for(int i=0;i<num;i++){int fd=eArr[i].data.fd;int es=eArr[i].events;printf("fd=[%d],es=[%d]\n", fd, es);if(fd == 0){//键盘输入char buf[64]={0};fgets(buf, sizeof(buf), stdin);buf[strlen(buf)-1]=0;printf("键盘输入了:%s\n", buf);ssize_t cnt=send(client, buf,strlen(buf),0);printf("发送了[%ld]:%s\n", cnt, buf);if(cnt == -1){perror("send error");}continue;}if(fd == client){//收到消息char buf[64]={0};ssize_t cnt=recv(fd, buf, sizeof(buf), 0);printf("收到[%ld]:%s\n", cnt, buf);continue;}//不知道fprintf(stderr, "错误的监听FD[%d]\n", fd);}}//epoll ctl del//epoll waitreturn 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/7188.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

一文了解Android的Doze模式

Android 的 Doze 模式是一项省电功能&#xff0c;主要用于减少设备的功耗&#xff0c;特别是在屏幕关闭且设备长时间未被使用的情况下。Doze 模式在 Android 6.0&#xff08;API Level 23&#xff09;首次引入&#xff0c;并在后续版本中不断改进&#xff0c;以便更智能地管理后…

Redis设计与实现 学习笔记 第十六章 Sentinel

Sentinel&#xff08;哨岗、哨兵&#xff09;是Redis的高可用性&#xff08;high availability&#xff09;解决方案&#xff1a;由一个或多个Sentinel实例&#xff08;instance&#xff09;组成的Sentinel系统可以监视任意多个主服务器&#xff0c;以及这些主服务器属下的从服…

I.MX6U 裸机开发3. GPIO操作控制LED灯

I.MX6U 裸机开发3. GPIO操作控制LED灯 一、创建项目目录及源文件1. 新建目录2. 远程开发环境3. 创建源文件 二、代码编写1. 打开时钟2. 配置端口复用功能为GPIO3. 配置端口电气属性4. 设置GPIO方向&#xff08;GDIR寄存器&#xff09;5. 输出6. 死循环等待 三、编译程序1. 整体…

雷军-2022.8小米创业思考-11-新零售:用电商思维做新零售,极致的效率+极致的体验。也有弯路,重回极致效率的轨道上。

第十一章 新零售 当我们说到小米模式的时候&#xff0c;其实我们说的是两件东西&#xff1a; 一是小米模式的本质&#xff0c;即高效率的商业模式&#xff1b; 另一件是小米这家公司具象的商业模式&#xff0c;这是小米在实践中摸索、建立的一整套业务模型。 从2015年到202…

Java:多态的调用

1.什么是多态 允许不同类的对象对同一消息做不同的响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。&#xff08;发送消息就是函数调用&#xff09;。多态使用了一种动态绑定&#xff08;dynamic binding&#xff09;技术&#xff0c;指在执行期间判断所引用…

基于Python的学生宿舍管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

基于springboot+vue实现的网上预约挂号管理系统 (源码+L文+ppt)4-104

结合现有六和医院网上预约挂号管理系统的特点&#xff0c;应用新技术&#xff0c;构建了六和医院网上预约挂号管理系统。首先从需求出发&#xff0c;对目前传统的六和医院网上预约挂号管理进行了详细的了解和分析。根据需求分析结果&#xff0c;对系统进行了设计&#xff0c;并…

C++初阶(九)--初识模板

目录 引入 一、什么是模板 二、函数模板 1.函数模板的概念 2.函数模板的格式 template关键字 模板参数列表 3.函数模板的原理 4.函数模板的实例化 5.数模板的匹配原则 三、类模板 1.类模板的定义格式 2.类模板的实例化 引入 在编程的世界里&#xff0c;我们经常…

C语言 | Leetcode C语言题解之第537题复数乘法

题目&#xff1a; 题解&#xff1a; bool parseComplexNumber(const char * num, int * real, int * image) {char *token strtok(num, "");*real atoi(token);token strtok(NULL, "i");*image atoi(token);return true; };char * complexNumberMulti…

牛客网项目总结

下面这幅图是牛客网项目的架构图&#xff0c;最下层是Spring Boot&#xff0c;表示我们所有的技术都是基于Spring Boot&#xff0c;上面一层是Spring&#xff0c;Spring上面是Spring MVC、Spring MyBatis 和 Spring Security。 通过Spring MVC 解决前后端请求交互的问题&#…

想画一个沙漠掘金游戏地图

想画一个沙漠掘金游戏地图 沙漠掘金生成一个地图htmljs 沙漠掘金 沙漠掘金是一个企业培训课程游戏&#xff0c;规则大致是&#xff1a; 玩家从大本营出发&#xff0c;到达矿山掘金后返回&#xff0c;如果规定的天数未回来&#xff0c;则失败&#xff0c;如果回来&#xff0c;…

【Java爬虫的淘宝寻宝记】—— 淘宝商品类目的“藏宝图”

引言&#xff1a; 在淘宝这个广袤的“商品宇宙”中&#xff0c;每一件商品都是一颗璀璨的星球&#xff0c;而商品类目就是连接这些星球的星际航道。今天&#xff0c;我们将派遣一位勇敢的Java爬虫宇航员&#xff0c;去揭开这些星际航道背后的秘密——商品类目。准备好了吗&…

内网穿透-SSF内网穿透反向socks代理之渗透内网thinkphp主机上线msf

1 ssf 简介 Secure Socket Funneling socks正反向代理&#xff0c;linux版较好的免杀 1.1下载地址 https://github.com/securesocketfunneling/ssf 1.2下载编译好的执行文件 https://github.com/securesocketfunneling/ssf/releases/tag/3.0.0 2.环境 kali 攻击机 网卡 桥…

【HarmonyOS】键盘遮挡输入框UI布局处理

【HarmonyOS】键盘遮挡输入框UI布局处理 问题背景&#xff1a; 在开发输入框UI时&#xff0c;特别是登录页面的密码输入框靠下&#xff0c;或者是评论底部的pop弹框。 当我们输入框获得焦点后&#xff0c;键盘自下而上显示&#xff0c;一般情况下会遮挡住我们的UI布局。 导致…

ssm基于BS的仓库在线管理系统的设计与实现+vue

系统包含&#xff1a;源码论文 所用技术&#xff1a;SpringBootVueSSMMybatisMysql 免费提供给大家参考或者学习&#xff0c;获取源码看文章最下面 需要定制看文章最下面 目 录 第一章 绪论 1 1.1 研究背景 1 1.2 研究意义 1 1.3 研究内容 2 第二章 开发环境与技术3 …

QML项目实战:自定义TextField

目录 一.添加模块 import QtQuick.Controls 1.2 import QtQuick.Controls.Styles 1.4 import QtGraphicalEffects 1.15 二.自定义TextField 1.属性设置 2.输入框设置 3.按钮开关 三.效果 1.readonly为false 2.readonly为true 四.代码 一.添加模块 import QtQuick.…

C++ | Leetcode C++题解之第523题连续的子数组和

题目&#xff1a; 题解&#xff1a; class Solution { public:bool checkSubarraySum(vector<int>& nums, int k) {int m nums.size();if (m < 2) {return false;}unordered_map<int, int> mp;mp[0] -1;int remainder 0;for (int i 0; i < m; i) {r…

AFL++实战入门与afl-fuzz流程解析(源码流程图)

简介 本项目为模糊测试的零基础教学,适合了解 pwn 且会使用 Linux 的 gcc、gdb 的读者。模糊测试旨在通过向程序投喂数据使其崩溃,从而获取崩溃样本以寻找程序漏洞。本文前半部分介绍 AFL++ 的 docker 环境配置,帮助读者解决入门时的环境和网络问题; 后半部分全面解析 afl…

Java 网络编程(一)—— UDP数据报套接字编程

概念 在网络编程中主要的对象有两个&#xff1a;客户端和服务器。客户端是提供请求的&#xff0c;归用户使用&#xff0c;发送的请求会被服务器接收&#xff0c;服务器根据请求做出响应&#xff0c;然后再将响应的数据包返回给客户端。 作为程序员&#xff0c;我们主要关心应…

用Python脚本执行安卓打包任务

这个样例是基于windows系统写的python打包安卓的脚本&#xff1a; 一、配置AndroidStudio下的打包任务 1.在Android项目根目录下的build.gradle文件配置生成Release包的任务&#xff1a; task cleanAll(type: Delete) {delete rootProject.buildDirrootProject.subprojects.e…