《UNIX网络编程》中第一个timer_server的例子

C++高性能跨平台网络编程实战:从IO模型到Boost.Asio应用 网络编程是构建分布式系统的基石,其核心在于高效管理海量并发连接与数据传输。从原理层面看,IO模型决定了程序处理网络请求的基本方式,其中IO多路复用技术通过单线程监控多个连接,显著提升了资源利用率。在技术价值上,高性能网络框架能够支撑游戏服务器、金融交易等低延迟、高吞吐场景。应用层协议设计(如长度前缀格式)与缓冲区优化(如零拷贝技术)是保障通信效率的关键实践。本文聚焦于C++领域,探讨如何利用Boost.Asio等现代库实现跨平台高性能网络服务,涵盖Reactor/Proactor模式选型、连接生命周期管理及 阅读详情

 1.配置环境

    在这里下载unpv13e.tar.gz,其中包含了《UNIX网络编程》第一卷的源代码。假设将其移到~/Unix/Network/目录下,以下为配置过程(假设当前目录为下载目录):

 
  1. mv ./unpv13e.tar.gz ~/Unix/Network 
  2.  
  3.     cd ~/Unix/Network
  4.  
  5.     tar -zxvf unpv13e.tar.gz 
  6.  
  7.     cd unpv13e
  8.  
  9.     ./configure 
  10.  
  11.     cd lib 
  12.  
  13.     make 
  14.  
  15.     cd ../                  #back to unpv13e/ 
  16.  
  17.     cp libunp.a /usr/lib 
  18.  
  19.     cp libunp.a /usr/lib64
  20.  
  21.     cd ../                  #back to Network/ 
  22.  
  23.     cp ./unpv13e/lib/unp.h ./ 
  24.  
  25.     cp ./unpv13e/config.h ./ 
  26.  
  27.     vi unp.h #使用vi将unp.h中的 #include "../config.h"改为#include "./config.h" 
  28.  
  29.     mkdir timer_server 
  30.  
  31.     cd timer_server 

2.编写代码    

 编写服务端代码:

 
  1. #include "../unp.h" 
  2.  
  3. int main(int argc,char *argv[]) 
  4. { 
  5.     int listenfd,connfd; 
  6.     struct sockaddr_in servaddr; 
  7.     char buff[MAXLINE]; 
  8.     time_t ticks; 
  9.     listenfd = Socket(AF_INET,SOCK_STREAM,0); 
  10.     bzero(&servaddr,sizeof(servaddr)); 
  11.     servaddr.sin_family = AF_INET; 
  12.     servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
  13.     servaddr.sin_port=htons(13); 
  14.     Bind(listenfd,(SA*)&servaddr,sizeof(servaddr)); 
  15.     Listen(listenfd,LISTENQ); 
  16.     for(;;) 
  17.     { 
  18.         connfd = Accept(listenfd,(SA*)NULL,NULL); 
  19.         ticks = time(NULL); 
  20.         snprintf(buff,sizeof(buff),"%.24s\r\n",ctime(&ticks)); 
  21.         Write(connfd,buff,strlen(buff)); 
  22.         Close(connfd); 
  23.     } 
  24.     return 0; 
  25. } 

      编写客户端代码:

 
  1. #include "../unp.h" 
  2.  
  3. int main(int argc,char *argv[]) 
  4. { 
  5.     int socketfd,n; 
  6.     char recvline[MAXLINE+1]; 
  7.     struct sockaddr_in servaddr; 
  8.     if(argc != 2) 
  9.         err_quit("Usage:%s <IP Address>",argv[0]); 
  10.     if( (socketfd = socket(AF_INET,SOCK_STREAM,0)) <0 ) 
  11.         err_sys("socket error"); 
  12.     bzero(&servaddr,sizeof(servaddr)); 
  13.     servaddr.sin_family = AF_INET; 
  14.     servaddr.sin_port = htons(13); 
  15.     if( inet_pton(AF_INET,argv[1],&servaddr.sin_addr) <= 0) 
  16.         err_quit("inet_pton error for %s .",argv[0]); 
  17.     if(connect(socketfd,(SA*)&servaddr,sizeof(servaddr))<0) 
  18.         err_sys("connecting error."); 
  19.     while( (n = read(socketfd,recvline,MAXLINE))>0){ 
  20.         recvline[n] = 0; 
  21.         if(fputs(recvline,stdout) == EOF) 
  22.             err_sys("read error"); 
  23.     } 
  24.     if(n<0) 
  25.         err_sys("read error"); 
  26.     return 0; 
  27. } 

         编译运行:

 
  1. $gcc server.c -o server -lunp 
  2. $gcc client.c -o client -lunp 
  3. $./server & 
  4. $./client 192.168.101.71 
  5. Mon Jul 16 17:37:45 2012 
  6. $./client 192.168.101.71 
  7. Mon Jul 16 17:37:47 2012 
  8. $./client 192.168.101.71 
  9. Mon Jul 16 17:37:47 2012 
  10. $./client 192.168.101.71 
  11. Mon Jul 16 17:37:49 2012  

      在读的时候有一个小技巧,就是使用循环的方式去读套接口中的数据而不是只读一次,这是由于需要的数据可能分成多节传过来。下面的代码将展示这一点:

 
  1. #include "../unp.h" 
  2.  
  3. int main(int argc,char *argv[]) 
  4. { 
  5.     int socketfd,n; 
  6.     char recvline[MAXLINE+1]; 
  7.     struct sockaddr_in servaddr; 
  8.     if(argc != 2) 
  9.         err_quit("Usage:%s <IP Address>",argv[0]); 
  10.     if( (socketfd = socket(AF_INET,SOCK_STREAM,0)) <0 ) 
  11.         err_sys("socket error"); 
  12.     bzero(&servaddr,sizeof(servaddr)); 
  13.     servaddr.sin_family = AF_INET; 
  14.     servaddr.sin_port = htons(13); 
  15.     if( inet_pton(AF_INET,argv[1],&servaddr.sin_addr) <= 0) 
  16.         err_quit("inet_pton error for %s .",argv[0]); 
  17.     if(connect(socketfd,(SA*)&servaddr,sizeof(servaddr))<0) 
  18.         err_sys("connecting error."); 
  19.     int counter = 0; 
  20.     while( (n = read(socketfd,recvline,MAXLINE))>0){ 
  21.         recvline[n] = 0; 
  22.         if(fputs(recvline,stdout) == EOF) 
  23.             err_sys("read error"); 
  24.         counter++; 
  25.     } 
  26.     printf("read operation :%d\n",counter); 
  27.     if(n<0) 
  28.         err_sys("read error"); 
  29.     return 0; 
  30. } 

        在循环中加入计数代码,用来统计计数的次数。然后我们将服务器端的代码改为for循环的形式:

 
  1. #include "../unp.h" 
  2.  
  3. #include<string.h> 
  4. int main(int argc,char *argv[]) 
  5. { 
  6.     int listenfd,connfd; 
  7.     struct sockaddr_in servaddr; 
  8.     char buff[MAXLINE]; 
  9.     time_t ticks; 
  10.     listenfd = Socket(AF_INET,SOCK_STREAM,0); 
  11.     bzero(&servaddr,sizeof(servaddr)); 
  12.     servaddr.sin_family = AF_INET; 
  13.     servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
  14.     servaddr.sin_port=htons(13); 
  15.     Bind(listenfd,(SA*)&servaddr,sizeof(servaddr)); 
  16.     Listen(listenfd,LISTENQ); 
  17.     for(;;) 
  18.     { 
  19.         connfd = Accept(listenfd,(SA*)NULL,NULL); 
  20.         ticks = time(NULL); 
  21.         snprintf(buff,sizeof(buff),"%.24s\r\n",ctime(&ticks)); 
  22.         int i = 0; 
  23.         int len = strlen(buff); 
  24.         for(i=0;i<len;i++) 
  25.             Write(connfd,&buff[i],sizeof(char)); 
  26.         Close(connfd); 
  27.     } 
  28.     return 0; 
  29. } 

        下面为运行效果:

         

 
  1. $ ./client 192.168.101.71 
  2. Mon Jul 16 21:24:05 2012 
  3. read operation :4 
  4. $ ./client 192.168.101.71 
  5. Mon Jul 16 21:24:05 2012 
  6. read operation :4 
  7. $ ./client 192.168.101.71 
  8. Mon Jul 16 21:24:05 2012 
  9. read operation :3 
  10. $ ./client 192.168.101.71 
  11. Mon Jul 16 21:24:06 2012 
  12. read operation :4 
  13. $ ./client 192.168.101.71 
  14. Mon Jul 16 21:24:06 2012 
  15. read operation :3 
  16. $ ./client 192.168.101.71 
  17. Mon Jul 16 21:24:07 2012 
  18. read operation :5 

 

本文出自 “相信并热爱着” 博客,请务必保留此出处http://hipercomer.blog.51cto.com/4415661/932671

C++网络编程实战:Boost.Asio异步模型与套接字编程详解 网络编程是构建分布式系统和网络应用的核心技术,其核心在于高效处理多并发连接与I/O操作。传统阻塞式套接字编程在应对C10K等高并发场景时面临性能瓶颈,因此异步I/O与事件驱动模型成为现代高性能网络框架的基石。Boost.Asio作为C++领域广泛使用的跨平台网络库,通过封装epoll、IOCP等系统级异步机制,提供了统一的Proactor模式接口,实现了真正的非阻塞I/O。其技术价值在于允许单线程或线程池高效管理海量连接,极大提升了程序的吞吐量与资源利用率,广泛应用于游戏服务器、金融交易系统、实时通信等高性 阅读详情

相关推荐

C++ Networking TS 实现解析:从执行器、协程到高性能网络编程实践

在现代C++网络编程中,异步编程模型是构建高并发、低延迟服务的核心技术。其核心原理在于将I/O操作与任务执行解耦,通过事件驱动机制提升系统吞吐量。这一技术的核心价值在于能够以极少的线程资源处理海量并发连接,显著提升资源利用率。其典型应用场景包括游戏服务器、金融交易系统、实时通信平台等对性能要求苛刻的领域。本文聚焦于C++ Networking TS(网络技术规范)的具体实现,深入剖析其核心组件——执行器(Executor)与完成令牌(Completion Token)。执行器作为异步操作的调度核心,决定了任

掬水月在手,弄花香满衣 441

Linux/Unix下几种实现定时的方式总结

定时器Timer应用场景非常广泛,在Linux下,有以下几种方法: 1. 使用sleep()和usleep() 其中sleep精度是1秒,usleep精度是1微妙,具体代码就不写了。使用这种方法缺点比较明显,在Linux系统中,sleep类函数不能保证精度,尤其在系统负载比较大时,sleep一般都会有超时现象。 2. 使用信号量SIGALRM + alarm() 这种方式的精度能达到1秒,其中利用了*nix系统的信号量机制,首先注册信号量SIGALRM处理函数,调用alarm(),设置定时长度,代码如下:

M2嵌入式 703

libhv网络库入门指南:从TCP/HTTP到WebSocket的C++高性能网络编程实践

网络编程是构建服务器后端、物联网网关和实时通信工具的核心技术,其关键在于高效管理多路IO连接。传统方案如libevent、libuv和Boost.Asio虽然功能强大,但学习曲线陡峭,API设计复杂。libhv作为一款国产开源网络库,通过封装底层IO多路复用机制(如epoll、kqueue),提供了统一的事件循环接口,显著降低了开发门槛。其技术价值在于将高性能与易用性结合,内置了HTTP、WebSocket、MQTT等高层协议支持,实现了“开箱即用”的开发体验。在应用场景上,libhv适用于需要快速搭建内网

weixin_33889245的博客 414

【RTOS学习】软件定时器 | 中断处理

讲解了软件定时器的概念,使用,运行机制和守护任务,还有中断发生以后的处理,以及中断服务函数和普通任务是如何进行通信的,两套API的差别对比。

weixin_63726869的博客 2293

从零构建C++ Web服务器:TinyWebServer核心架构与事件驱动模型详解

Web服务器是网络编程的核心组件,其本质是基于TCP/IP协议栈实现的高并发服务端程序。理解其工作原理需要掌握socket编程、IO多路复用和事件驱动模型等基础概念。通过Reactor模式,服务器能够高效处理海量连接,将IO事件分发与业务逻辑处理解耦,从而提升系统吞吐量。在工程实践中,线程池、连接池和定时器等资源管理技术对性能优化至关重要。本文以TinyWebServer项目为例,深入剖析其main.cpp入口逻辑与WebServer类的事件循环机制,详解epoll的LT/ET触发模式选择、连接管理映射和优

weixin_34194087的博客 427

Linux C开发实战:从基础模块到项目构建的工程化指南

在Linux系统编程和C语言开发领域,掌握核心概念与工程实践是构建稳定、高效应用的基础。从内存管理、文件I/O到进程间通信,其原理在于操作系统对底层资源的抽象与管理。这些技术的核心价值在于能够直接控制系统资源,实现高性能、低延迟的软件,尤其在嵌入式系统、服务器后端和高性能计算等场景中至关重要。本文聚焦于Linux C开发的工程化实践,通过剖析一个典型的实战代码集合,深入探讨了网络编程中epoll的边缘触发模式与错误处理机制,以及多线程并发下的资源管理策略,为开发者提供了从模块学习到项目集成的完整路径。

weixin_30693683的博客 436

centos7安装配置consul

注意 consul 一般通过内网 IP 连接 安装 cd /usr/local/consul wgethttps://releases.hashicorp.com/consul/1.2.1/consul_1.2.1_linux_amd64.zip unzip -qconsul_1.2.1_linux_amd64.zip [root@server1 consul]# cat /...

小李子 751

Rust实现用户态TCP协议栈:从原理到高性能网络编程实践

TCP协议作为网络通信的核心基础,通过可靠传输、流量控制和拥塞避免机制保证了数据的有序交付。其工作原理基于状态机管理和滑动窗口机制,通过三次握手建立连接、序列号保证数据顺序、确认机制处理丢包重传。在技术价值层面,用户态TCP协议栈能够避免内核上下文切换开销,实现零拷贝数据传输和自定义流量控制算法。这种技术特别适用于需要极致性能的网络中间件、自定义协议网关和高频交易系统等场景。本文基于Rust语言的内存安全特性和异步并发优势,深入探讨TCP状态机、滑动窗口和拥塞控制算法的实现细节,为构建高性能网络应用提供实践

wangqiaowqo的专栏 162

netty(四) NIO创建的TimerServer源码分析之服务端

NIO创建的TimeServer源码分析 我们将在TimeServer历程中给出完整的NIO创建的时间服务器源码。public class TimerServer { public static void main(String[] args) throws IOException { int port = 8080; if (args != null &

lz710117239的博客 554

C++高性能Web服务器:从阻塞I/O到事件驱动架构的实践

在网络编程中,I/O模型是决定服务性能的核心。传统的阻塞式I/O模型为每个连接分配独立线程,在并发量上升时面临资源消耗大、可扩展性差的问题。其原理是线程在数据未就绪时会进入等待状态,导致CPU空闲和频繁的上下文切换。为了解决这一瓶颈,非阻塞I/O与事件驱动模型应运而生,通过I/O多路复用技术(如kqueue、epoll)实现单线程管理大量连接,极大地提升了资源利用率和系统吞吐量。这一技术价值在于能够以极低的资源开销支撑数万甚至数十万的并发连接,特别适用于高并发的网络服务场景,如实时通信、API网关和微服务架

weixin_33698043的博客 428

C++ WebSocket++实战:从零构建高性能实时通信服务端

WebSocket协议是实现全双工、低延迟实时通信的核心技术,它通过在单个TCP连接上建立持久通道,克服了HTTP轮询的高开销与延迟问题,为在线游戏、金融推送、物联网等场景提供了高效的底层支持。其技术价值在于实现了真正的服务器主动推送,大幅提升了实时应用的交互体验与系统吞吐量。基于Asio异步网络库构建的WebSocket++,作为一个纯头文件的C++库,封装了复杂的协议细节,为开发者提供了简洁高效的API。通过合理运用多线程模型与连接管理机制,可以轻松构建出支持高并发连接的生产级服务。本文以WebSock

weixin_30562507的博客 377

Unix/Linux编程:POSIX间隔式定时器

POSIX间隔式定时器 使用setitimer来设置Unix间隔式定时器,会由如下几个问题: 针对ITIMER_REAL、ITIMER_VIRTUAL 和 ITIMER_PROF 这 3 类定时器,每种只能设置一个 只能通过发送信号的方式来通知定时器到期。另外,也不能改变到期时产生的信号 如果一个间隔式定时器到期多次,而且相应信号遭到阻塞时,那么会只调用一次信号处理器函数。换句话说,无从知晓是否出现过定时器溢出的情况 定时器的分辨率只能达到微秒级。不过,一些系统的硬件时钟提供了更为精细的时钟分辨率,软件此

OceanStar的博客 1666

【 史上最全】测绘、遥感RS、地信GIS国家级比赛竞赛整理

目录Esri Esri

weixin_43910227的博客 9153

网络编程:PHP 实现 “IO多路复用模型 - select“

标题

wangbeilin123的专栏 335

sap外币重估流程图_SAP 外币评估方法(Valuation Method,评估方法)

在FI-GL模块评估外币时(T-code:F.05),需要输入ValuationMethod。下面分解一下评估方法是如何定义的。IMG -> FI -> General LedgerAccounting ->Business Transactions ->Closing ->Valuating -> ForeignCurrency Valuation ->...

weixin_39640543的博客 2356

命令行驱动视频剪辑:cutcli与AI自动化工作流实战

在视频内容创作领域,自动化与批量化处理是提升生产效率的关键。传统图形界面工具在应对重复性任务时往往效率低下,而通过命令行接口(CLI)驱动视频生成,则能实现流程的程序化控制。其技术原理在于将视频结构抽象为可编程的指令序列,通过解析命令生成标准化的工程文件。这种模式的核心价值在于将视频制作从手动操作转变为代码驱动,特别适合与AI编程助手集成,实现自然语言到视频草稿的自动转换。应用场景广泛覆盖社交媒体内容批量生产、教育视频自动化生成、数据可视化视频组装等领域。本文以cutcli工具为例,深入解析如何通过命令行与

weixin_42520239的博客 578

Java 网络编程与进程间通信总结

本文探讨了Java网络编程中的两个核心问题:TCP粘包/拆包问题的解决方案和基于NIO的高并发聊天服务器实现。首先详细分析了TCP粘包/拆包现象的根本原因,对比了四种解决方案(固定长度、分隔符、长度字段和特殊协议),重点推荐了工业级的长度字段方案,并给出了Netty框架的使用建议。其次,针对高并发场景,提出了单Reactor多线程模型的NIO实现方案,包括架构设计和关键代码片段,展示了如何通过Selector机制处理大量并发连接。文章强调在处理网络通信时,必须考虑半包/粘包问题,并合理选择高性能IO模型来应

qq_44938023的博客 229

PCB压合原理与工艺全流程深度解析

PCB压合是多层印制电路板制造中的核心工序,其本质并非简单物理叠加,而是高分子树脂流动、玻璃布应力释放、铜箔热膨胀及界面能调控的协同过程。理解压合原理,需掌握温度-压力-时间三维曲线动态关系;优化工艺流程,须兼顾叠板精度、热压参数匹配与冷却策略;关键影响因素如半固化片(PP)选型、铜箔表面处理、设备温场均匀性、结构对称性、环境湿度及操作手法,共同决定层间结合力、翘曲度与孔壁质量。本文围绕PCB压合原理、工艺流程、关键影响因素三大维度展开,融合IPC标准、实测数据与产线案例,为工艺工程师、NPI人员及设备维护

weixin_29191081的博客 258

Linux C语言实现进程心跳监控:基于UDS与timerfd的高可用守护方案

在Linux后台服务与分布式系统中,进程存活监控是保障服务可用性的基础机制。其核心原理是通过进程间通信(IPC)让被监控进程定期向监控端发送存活信号,监控端在超时未收到信号时判定进程异常并触发恢复流程,从而提升系统的容错与自愈能力。这一技术价值在于能有效检测进程僵死、卡死等操作系统无法自动处理的故障状态,广泛应用于微服务、数据库连接池、长连接服务等对可靠性要求高的场景。本文聚焦于使用C语言在Linux环境下实现一个轻量级、生产可用的进程心跳机制,详细剖析了如何利用Unix Domain Socket(UDS

weixin_30784501的博客 400

NXP(imx8qxp)系列DDR校准以及android镜像烧录

文章目录一、 不得不吐槽以下nxp的这个代码镜像烧写的过程,做得太开源了,导致镜像根本烧录不进去,实属令人头痛。 一、

永不秃头的程序员的博客 5991

【NVMEM子系统】二、NVMEM驱动框架

该子系统整体架构不算太大,还是比较容易去理解的,下面我们一起去一探究竟!,该子系统主要用于实现EEPROMEfuse等非易失存储器的统一管理。在早期,像EEPROM驱动是存放于目录下,由于没有做到好的抽象,每次需要去访问相应内存空间,都需要去复制几乎一样的代码,去注册sysfs,这是一个相当大的抽象泄露。NVMEM子系统就是为了解决以往的抽象泄露问题。

Donge's Blog 1715

NTP v4 协议解析:从 1900 到 1970 的 2208988800 秒偏移量计算与代码实现

本文深入解析NTPv4协议中2208988800秒偏移量的数学原理与工程实现,详细介绍了从1900到1970年的时间计算方法和代码实现。探讨了NTP时间戳的二进制结构、客户端核心算法及多平台集成方案,为构建高精度网络时间同步系统提供实践指导。

weixin_30292843的博客 404

【OpenClaw企业级智能体实战】第13篇:1+N架构实战!OpenClaw多Agent数字员工军团搭建指南(含完整配置+路由策略+代码落地)

单Agent因“记忆负担重、Token消耗高、响应不精准”已难以满足复杂场景需求,而多Agent团队通过“1个编排者+N个执行者”的分工协作模式,能让效率提升300%以上。本文基于OpenClaw 2026稳定版,结合阿里云开发者社区实战案例,从核心认知、准备工作、实操流程、协作机制、安全配置五大维度,完整拆解多Agent团队搭建全流程。文中包含可直接复制执行的代码、详细配置模板、路由策略设置及常见问题排查,新手可在1-2小时内落地属于自己的“数字员工”军团,覆盖内容创作、技术支持、多平台运营等多场景。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 746
上一篇: 百度实习生招聘的一道大数据处理题目(上)
下一篇: 【pthread系列-8】POSIX线程中的“一次初始化”
下木
博客等级 码龄16年 88粉丝 132原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值