linux c socket之异步IO

2023-11-15

[cpp]  view plain copy
  1. /*  
  2.  * File:   UDPEchoClient-TimeOut.c 
  3.  * Author: 云守护 
  4.  */  
  5. #include <stdio.h>  
  6. #include <stdlib.h>  
  7. #include <string.h>  
  8. #include <unistd.h>  
  9. #include <errno.h>  
  10. #include <signal.h>  
  11. #include <sys/socket.h>  
  12. #include <netinet/in.h>  
  13. #include <netdb.h>  
  14. #include "DieWithMessage.h"  
  15. //超时设置  
  16. static const unsigned int TIMEOUT_SEC=3;  
  17. //重连次数  
  18. static const unsigned int MAXTRIES=5;  
  19. //已经尝试次数  
  20. unsigned int tries=0;  
  21. //闹铃到来处理函数,超时时间到  
  22. void CatchAlarm(int ignored);  
  23. int main(int argc, char** argv) {  
  24.     if(argc<3||argc>4)  
  25.         DieWithUserMessage("param","<Server Address/Name> <Echo Word> [<Server port/service>]\n");  
  26.     char *server=argv[1];  
  27.     char* echoString=argv[2];  
  28.     size_t echoStringLen=strlen(echoString);  
  29.     if(echoStringLen>1024*8)  
  30.         DieWithUserMessage(echoString,"too long");  
  31.     char * service=(argc==4)?argv[3]:"echo";  
  32.     //配置地址信息  
  33.     struct addrinfo addr_criteria;  
  34.     memset(&addr_criteria,0,sizeof(addr_criteria));  
  35.     addr_criteria.ai_family=AF_UNSPEC;  
  36.     addr_criteria.ai_socktype=SOCK_DGRAM;  
  37.     addr_criteria.ai_protocol=IPPROTO_UDP;  
  38.       
  39.     struct addrinfo *server_addr;  
  40.     //自动获取地址信息  
  41.     int ret=getaddrinfo(server,service,&addr_criteria,&server_addr);  
  42.     if(ret!=0)  
  43.         DieWithUserMessage("getaddrinfo() failed!",gai_strerror(ret));  
  44.     //建立socket  
  45.     int sock=socket(server_addr->ai_family,server_addr->ai_socktype,server_addr->ai_protocol);  
  46.     if(sock<0)  
  47.         DieWithSystemMessage("socket failed!");  
  48.     //信号处理者  
  49.     struct sigaction handler;  
  50.     //设置SIGALRM信号到来处理函数  
  51.     handler.sa_handler=CatchAlarm;  
  52.     //填充信号掩码  
  53.     if(sigfillset(&handler.sa_mask)<0)  
  54.         DieWithSystemMessage("sigfillset() failed!");  
  55.     //信号标志归零  
  56.     handler.sa_flags=0;  
  57.     //注册信号量  
  58.     if(sigaction(SIGALRM,&handler,0)<0)  
  59.         DieWithSystemMessage("sigaction() failed for SIGALRM");  
  60.     //开始发送数据  
  61.     ssize_t numBytes=sendto(sock,echoString,echoStringLen,0,server_addr->ai_addr,server_addr->ai_addrlen);  
  62.     if(numBytes<0)  
  63.         DieWithSystemMessage("send() failed!");  
  64.     else if(numBytes!=echoStringLen)  
  65.     {  
  66.         DieWithUserMessage("sendto() error","sent unexpected number of bytes");          
  67.     }  
  68.     //然后接收数据,都是循环接收的  
  69.     struct sockaddr_storage fromaddr;  
  70.     socklen_t fromaddrLen=sizeof(fromaddr);  
  71.     //设置定时器,超时设置  
  72.     alarm(TIMEOUT_SEC);  
  73.     char buffer[BUFSIZ+1];  
  74.     //接收数据  
  75.     while((numBytes=recvfrom(sock,buffer,BUFSIZ,0,(struct sockaddr*)&fromaddr,&fromaddrLen))<0)  
  76.     {  
  77.         if(errno=EINTR)//闹铃响了,即超时了。执行了CatchAlarm  
  78.         {  
  79.             if(tries<MAXTRIES)  
  80.             {   //小于重试次数,继续重新发送数据  
  81.                 numBytes=sendto(sock,echoString,echoStringLen,0,(struct sockaddr*)server_addr->ai_addr,server_addr->ai_addrlen);  
  82.                 if(numBytes<0)  
  83.                     DieWithSystemMessage("sendto() failed!");  
  84.                 else if(numBytes!=echoStringLen)  
  85.                 {  
  86.                     DieWithUserMessage("sendto() error","sent unexpected number of bytes");  
  87.                 }  
  88.             }else{  
  89.                 DieWithUserMessage("No Response","Unable to communitcate with server");  
  90.             }  
  91.         }else{  
  92.             DieWithSystemMessage("recvfrom() failed!");  
  93.               
  94.         }  
  95.     }  
  96.     //闹铃归零  
  97.     alarm(0);  
  98.     buffer[echoStringLen]='\0';  
  99.     printf("Received: %s \n",buffer);  
  100.     close(sock);  
  101.     return (EXIT_SUCCESS);  
  102. }  
  103. //闹铃响了,执行该函数  
  104. void CatchAlarm(int ignored){  
  105.     tries+=1;  
  106. }  

[cpp]  view plain copy
  1. /*  
  2.  * File:   UDPEchoServer-SIGIO.c 
  3.  * Author: 云守护 
  4.  */  
  5. #include <stdio.h>  
  6. #include <stdlib.h>  
  7. #include <string.h>  
  8. #include <unistd.h>  
  9. #include <fcntl.h>  
  10. #include <sys/file.h>  
  11. #include <signal.h>  
  12. #include <errno.h>  
  13. #include <sys/types.h>  
  14. #include <sys/socket.h>  
  15. #include <netdb.h>  
  16. #include "DieWithMessage.h"  
  17. //用户空闲时任务  
  18. void UseIdleTime();  
  19. //异步IO处理者  
  20. void SIGIOHandler(int signalType);  
  21. int server_sock;  
  22. #define MAXSTRINGLENGTH 1024*8  
  23.   
  24. //打印客户端地址消息  
  25. void PrintSocketAddress(const struct sockaddr *address, FILE *stream) {  
  26.   // Test for address and stream  
  27.   if (address == NULL || stream == NULL)  
  28.     return;  
  29.   
  30.   void *numericAddress; // Pointer to binary address  
  31.   // Buffer to contain result (IPv6 sufficient to hold IPv4)  
  32.   char addrBuffer[INET6_ADDRSTRLEN];  
  33.   in_port_t port; // Port to print  
  34.   // Set pointer to address based on address family  
  35.   switch (address->sa_family) {  
  36.   case AF_INET:  
  37.     numericAddress = &((struct sockaddr_in *) address)->sin_addr;  
  38.     port = ntohs(((struct sockaddr_in *) address)->sin_port);  
  39.     break;  
  40.   case AF_INET6:  
  41.     numericAddress = &((struct sockaddr_in6 *) address)->sin6_addr;  
  42.     port = ntohs(((struct sockaddr_in6 *) address)->sin6_port);  
  43.     break;  
  44.   default:  
  45.     fputs("[unknown type]", stream);    // Unhandled type  
  46.     return;  
  47.   }  
  48.   // Convert binary to printable address  
  49.   if (inet_ntop(address->sa_family, numericAddress, addrBuffer,  
  50.       sizeof(addrBuffer)) == NULL)  
  51.     fputs("[invalid address]", stream); // Unable to convert  
  52.   else {  
  53.     fprintf(stream, "%s", addrBuffer);  
  54.     if (port != 0)                // Zero not valid in any socket addr  
  55.       fprintf(stream, "-%u", port);  
  56.   }  
  57. }  
  58.   
  59. int main(int argc, char** argv) {  
  60.     if(argc!=2)  
  61.         DieWithUserMessage("param","<server port/service>");  
  62.     char *service=argv[1];  
  63.     //配置地址信息  
  64.     struct addrinfo addr_criteria;  
  65.     memset(&addr_criteria,0,sizeof(addr_criteria));  
  66.     addr_criteria.ai_family=AF_UNSPEC; //地址族  
  67.     addr_criteria.ai_flags=AI_PASSIVE;  
  68.     addr_criteria.ai_socktype=SOCK_DGRAM; //流  
  69.     addr_criteria.ai_protocol=IPPROTO_UDP;//UDP  
  70.       
  71.     struct addrinfo *server_addr;  
  72.     //自动获取,消除IP4和IP6的依赖  getaddrinfo() is reentrant and allows programs to eliminate IPv4-versus-IPv6 depen‐ dencies.  
  73.     int retVal=getaddrinfo(NULL,service,&addr_criteria,&server_addr);  
  74.     if(retVal!=0)  
  75.         DieWithUserMessage("getaddrinfo() failed!",gai_strerror(retVal));  
  76.     //建立socket  
  77.     server_sock=socket(server_addr->ai_family,server_addr->ai_socktype,server_addr->ai_protocol);  
  78.     if(server_sock<0)  
  79.         DieWithSystemMessage("socket() failed!");  
  80.     //绑定端口  
  81.     if(bind(server_sock,server_addr->ai_addr,server_addr->ai_addrlen)<0)  
  82.     {  
  83.         DieWithSystemMessage("bind() failed!");  
  84.     }  
  85.     freeaddrinfo(server_addr);  
  86.       
  87.     printf("server success %s\n",service);  
  88.     //操作信号,设置异步IO  
  89.     struct sigaction handler;  
  90.     //设置异步到来时的处理函数  
  91.     handler.sa_handler=SIGIOHandler;  
  92.     //填充信号掩码  
  93.     if(sigfillset(&handler.sa_mask)<0)  
  94.         DieWithSystemMessage("sigfillset() failed!");  
  95.     //标志设置0,即无标志  
  96.     handler.sa_flags=0;  
  97.     //注册SIGIO信号  
  98.     if(sigaction(SIGIO,&handler,0)<0)  
  99.         DieWithSystemMessage("sigaction() failed for SIGIO");  
  100.     //设置server_sock接收SIGIO信号信息  
  101.     if(fcntl(server_sock,F_SETOWN,getpid())<0)  
  102.         DieWithSystemMessage("fcntl failed!");  
  103.     //使用非阻塞IO和SIGIO信号发送  
  104.     if(fcntl(server_sock,F_SETFL,O_NONBLOCK|FASYNC)<0)  
  105.         DieWithSystemMessage("Unable to put client sock into non-blocking/async mode");  
  106.     for(;;)  
  107.     {  
  108.         //死循环,等待异步IO的到来。就不用使用多线程了。  
  109.         UseIdleTime();  
  110.     }  
  111.     return (EXIT_SUCCESS);  
  112. }  
  113. void UseIdleTime()  
  114. {  
  115.     puts(".");  
  116.     sleep(3);//3s  
  117. }  
  118. //异步IO处理函数  
  119. void SIGIOHandler(int signalType)  
  120. {  
  121.     ssize_t numBytesRcvd;  
  122.     do{  
  123.         //只要有输入  
  124.         struct sockaddr_storage client_addr;  
  125.         size_t client_Len=sizeof(client_addr);  
  126.         char buffer[MAXSTRINGLENGTH];  
  127.         //接收数据  
  128.         numBytesRcvd=recvfrom(server_sock,buffer,MAXSTRINGLENGTH,0,(struct sockaddr*)&client_addr,&client_Len);  
  129.         if(numBytesRcvd<0)  
  130.         {  
  131.             if(errno!=EWOULDBLOCK)  
  132.             {  
  133.                 //判断recvfrom函数是否阻塞  
  134.                 DieWithSystemMessage("recvfrom failed!");  
  135.             }  
  136.         }else{  
  137.                 fprintf(stdout,"handling client ");  
  138.                 //打印地址消息  
  139.                 PrintSocketAddress((struct sockaddr*)&client_addr,stdout);  
  140.                 fputc('\n',stdout);  
  141.                 //把数据发送回去  
  142.                 ssize_t numByteSent=sendto(server_sock,buffer,numBytesRcvd,0,(struct sockaddr*)&client_addr,sizeof(client_addr));  
  143.                 if(numByteSent<0)  
  144.                     DieWithSystemMessage("sendto() failed!");  
  145.                 else if(numByteSent!=numBytesRcvd)  
  146.                 {  
  147.                     DieWithUserMessage("sendto()","sent unexpected number of bytes");  
  148.                       
  149.                 }  
  150.         }  
  151.         //循环接收数据  
  152.     }while(numBytesRcvd>=0);  
  153.       
  154. }  

[cpp]  view plain copy
  1. /*  
  2.  * File:   DieWithMessage.h 
  3.  * Author: root 
  4.  * 
  5.  * Created on 2013年11月13日, 下午3:52 
  6.  */  
  7.   
  8. #ifndef DIEWITHMESSAGE_H  
  9. #define DIEWITHMESSAGE_H  
  10.   
  11. #ifdef  __cplusplus  
  12. extern "C" {  
  13. #endif  
  14. #include <stdio.h>  
  15. #include <stdlib.h>  
  16.  void  DieWithUserMessage(const char *msg,const char * detail)  
  17.  {  
  18.      fputs(msg,stderr);  
  19.      fputs(":",stderr);  
  20.      fputs(detail,stderr);  
  21.      fputs("\n",stderr);  
  22.      exit(1);  
  23.  }  
  24.  void DieWithSystemMessage(const char* msg)  
  25.  {  
  26.      perror(msg);  
  27.      exit(1);  
  28.  }  
  29.   
  30.   
  31.   
  32. #ifdef  __cplusplus  
  33. }  
  34. #endif  
  35.   
  36. #endif  /* DIEWITHMESSAGE_H */  



FROM;http://blog.csdn.net/earbao/article/details/16337639


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux c socket之异步IO 的相关文章

  • linux网络编程实现投票功能

    投票系统 1 说明 写了一个投票系统 过程是先配置好服务器 在写一个网上投票功能 要实现网上投票功能 其实功能实现还是很简单的 麻烦一点的在于过程比较繁杂 要做的东西还是挺多的 2 过程 第一步 配置httpd服务器 先配置好httpd服务
  • whois命令常见用法

    whois命令常见用法 whois命令简介 安装whois Windows使用whois Linux安装whois whois常见用法 Linux下whois查询域名注册信息 whois命令简介 whois就是一个用来查询域名是否已经被注册
  • C++在线五子棋对战(网页版)项目:websocket协议

    目标 认识理解websocket协议 websocket切换过程和websocket协议格式 认识和学会使用websocketpp库常用接口 了解websocketpp库搭建服务器流程 认识和学会使用websocketpp库bin接口 最后
  • 使用sersync实现数据实时同步

    使用sersync实现数据实时同步 sersync诞生过程 部署前提 配置rsync服务端 部署sersync 配置sersync的path变量 修改sersync配置文件 sersync常用参数 使用服务文件实现开机自启动 实时同步服务d
  • webbench剖析

    webbench 其为linux上一款web性能压力测试工具 它最多可以模拟3万个并发连接数来测试服务器压力 其原理为fork多个子进程 每个子进程都循环做web访问测试 子进程将访问的结果通过管道告诉父进程 父进程做最终结果统计 其主要原
  • Linux下socket异步通讯聊天程序

    Linux下socket异步通讯聊天程序 转 original from http yangqi org linux socket asynchronous im system Posted by yangqi 2010年02月17日 We
  • socket阻塞与非阻塞,同步与异步、I/O模型

    socket阻塞与非阻塞 同步与异步 作者 huangguisu 1 概念理解 在进行网络编程时 我们常常见到同步 Sync 异步 Async 阻塞 Block 非阻塞 Unblock 四种调用方式 同步 所谓同步 就是在发出一个功能调用时
  • Linux网络通信总结

    网络IO之阻塞 非阻塞 同步 异步 单播 多播 组播 广播 多路复用POLL SELECT epoll 超时 read write accept connect 超时 实现 1 用select来设置超时机制 2 使用setsockopt 函
  • 基于tcpdump实例讲解TCP/IP协议

    前言 虽然网络编程的socket大家很多都会操作 但是很多还是不熟悉socket编程中 底层TCP IP协议的交互过程 本文会一个简单的客户端程序和服务端程序的交互过程 使用tcpdump抓包 实例讲解客户端和服务端的TCP IP交互细节
  • 基于epoll的聊天室程序

    epoll相对于poll和select这两个多路复用的I O模型更加的高效 epoll的函数很简单 麻烦的地方在于水平出发和边沿触发 用张图来说明下 ET 边沿 只是在状态反转时触发 比如从不可读到可读 而LT 水平 就是如果可读 就会一直
  • linux系统PXE自动装机无人值守

    PXE高效批量网络装机 PXE服务允许客户机通过网络从远程服务器下载引导镜像 并安装文件或整个操作系统 必须满足的前提条件 客户机的网卡支持PXE协议 且主板支持网络引导 网络中有一台DHCP服务器为客户机分配地址 指定引导文件位置 服务器
  • Linux网络编程一步一步学 - 目录(汇总)zhuan

    非常好的关于Linux网络编程的文章 我也是无意中在别人的博客里发现的 在网上搜了一下 这类的文章总共还有很多篇 最后我找到了原作者的姓名 周立发 以及作者的博客空间 本人坚决支持原创 在此将其文章进行了汇总 并且空间首页加入了他的博客链接
  • 【网络自定向下的学习】——TCP3次握手和4次挥手详解

    目录 前言 一 可靠数据传输 1 确认应答机制 2 超时重传机制 二 建立连接 三次握手 1 建立连接的过程 2 为什么会有三次握手 3 三次握手可以携带数据吗 4 什么是半连接队列 三 断开连接 4次挥手 1 4次挥手的过程 2 为什么连
  • linux下异步RPC的阶段性总结-非阻塞SOCKET客户端

    尽可能使用非阻塞socket int flags s flags fcntl fd F GETFL 0 if flags 1 close fd return 1 flags O NONBLOCK s fcntl fd F SETFL fla
  • TCP通信流程解析

    B S通信简述 整个计算机网络的实现体现为协议的实现 TCP IP协议是Internet的核心协议 HTTP协议是比TCP更高层次的应用层协议 HTTP HyperText Transfer Protocol 超文本传输协议 是互联网上应用
  • linux c socket之异步IO

    cpp view plain copy File UDPEchoClient TimeOut c Author 云守护 include
  • 【网络】——UDP复习笔记

    目录 1 UDP报文结构 2 UDP缓冲区 3 UDP特点 4 课后题 1 UDP报文结构 2 UDP缓冲区 UDP没有真正意义上的发送缓冲区 应用层调用sendto 函数直接将数据应用层的数据拷贝给传输层 传输层再构建UDP报头 然后再交
  • linux非阻塞socket教程

    本文并非解释什么是非阻塞socket 也不是介绍socket API的用法 取而代替的是让你感受实际工作中的代码编写 虽然很简陋 但你可以通过man手册与其它资源非富你的代码 请注意本教程所说的主题 如果细说 内容可以达到一本书内容 你会发
  • 【IP协议(一)】——IP数据报格式及其含义,IP数据报的切分

    个人主页 努力学习的少年 版权 本文由 努力学习的少年 原创 在CSDN首发 需要转载请联系博主 如果文章对你有帮助 欢迎关注 点赞 收藏 一键三连 和订阅专栏哦 IP数据报格式 版本 占4位 指ip协议的版本 首部长度 表示IP数据报中报
  • 【网络自定向下学习】——TCP报文段的详细解析

    个人主页 努力学习的少年 版权 本文由 努力学习的少年 原创 在CSDN首发 需要转载请联系博主 如果文章对你有帮助 欢迎关注 点赞 收藏 一键三连 和订阅专栏哦 目录 一 Tcp报文段的结构 二 首部长度 三 窗口大小 四 序列号和确认序

随机推荐

  • url服务器显示错误,服务器地址 (URL) 错误无效错误 - Dynamics 365 Sales

    为 Outlook 配置 时 URL Microsoft Dynamics CRM 无效 错误 3 31 2021 本文内容 本文提供了当您尝试将 Outlook 的 Microsoft Dynamics CRM 连接到您的 Microso
  • st语言编程手册plc_三菱Q系列PLC,ST语言的IF语句、CASE语句指令格式

    IF语句和CASE语句是ST编程语言中的选择 条件 语句的两种形式 1 如果 IF BOOL事件 1 0 那么 THEN 结果 语句 END IF 2 如果 IF BOOL事件 1 0 那么 THEN 结果 语句1 否则ELSE 语句2 E
  • Python 对加减乘除分别封装一个函数进行计算,参数是两个数,返回值是计算结果

    1 对加减乘除分别封装一个函数进行计算 参数是两个数 返回值是计算结果 def add x y param x param y return 返回结果 print x y return add 3 4 def sub x y param x
  • 动态菜单/权限管理的实现

    权限管理 序 现在基本上大大小小的系统都由权限分配这一基础功能 不同的用户看到的界面不一样 能够使用的功能也不会尽然相同 所以我要让我的系统做到超级管理员可以看到 操作所有界面 而新闻管理员只能看到新闻管理模块 仓库管理员只能看到仓库管理模
  • 基于openwrt,aria2下载器安装与配置

    迅雷下载不好用 所以用这个下载器aria2 需要安装软件 在可用软件列表中安装aria2和luci app aria2 安装完后有可能需要重启路由器 需要注意的问题 1 aria2只是一个下载工具 并没有图形界面 2 文件下载的位置 在ar
  • 在传统公司干IT是一种什么体验(六)

    不要轻视任何一家传统公司 传统公司能够在激烈的竞争中活下来 都有自己的绝活 表哥语录 表哥虽然经常吐槽自己的公司 但是大部分都是对传统公司的文化和风格的不适应 任何一家传统公司 能够在长达十几年甚至几十年的市场竞争中活下来 一定有自己的独门
  • 数据库开发之MySql(下)(多表查询)

    多表查询 介绍 多表查询就是指从多张表中查询数据 笛卡尔积 笛卡尔乘积是指在数学中 两个集合A集合 和 B集合的所有组合情况 在多表查询时 需要消除无效的笛卡尔积 怎么做多表查询的需求 要查询的数据涉及到哪些表 找出关联条件 外键 主键 其
  • STM32---独立看门狗

    文章目录 前言 一 看门狗概述 1 背景 2 工作原理 二 使用步骤 1 添加复位检测代码 2 喂狗时间设置 3 喂狗 4 喂狗技巧 三 应用领域 四 源码地址 总结 前言 STM32 独立看门狗 提示 以下是本篇文章正文内容 下面案例可供
  • RuntimeError: expected scalar type Long but found Float

    通过检查打印数据格式 发现数据是 torch int64 将数据转换成 float即可 torch tensor data dtype torch float
  • jwt生成token和验证token以及获取playload的数据,实现token拦截

    jwt实现流程 1 添加依赖
  • 常用性能测试工具介绍

    市面上常用的两款性能测试工具 1 LoadRunner 2 Jmeter Loadrunner 特点 1 工业化的性能测试工具 能支持大量用户 提供详细的报表来提供测试分析的数据 2 支持的协议多 3 使用 C 语言来编写的 优点 1 支持
  • kettle数据迁移

    kettle数据迁移 此处是将mysql数据库中的表修改表名与字段名迁移至另一个mysql数据库 1 kettle安装 1 1 kettle下载 8 3 0 0 371版本 Kettle各个版本下载地址 1 2 下载连接驱动包 mysql驱
  • QT QtableView的使用示例(设置item背景颜色的方法)

    1 创建表格内容 QStandardItemModel m standardItemModel new QStandardItemModel this QStandardItem item new QStandardItem 李四 m st
  • 解析数组里面包含数组的json格式的数据代码

    格式如图所示 操作代码如下 public class ActivityJuankuanInfoPost 获取捐款详情 public static JuankuanInfoMessageActivity applyactivityPost S
  • SmartRefreshLayout 嵌套reycleview 长按排序下拉刷新

    布局文件
  • 如何判断数码管是共阴极还是共阳极

    开发环境 蓝色粗体字为特别注意内容 1 硬件环境 8位数码管 引脚排布如下 方法一 限流电阻 简单 用5V电源接一个限流电阻 假一定个是阳极或是阴极 另一个挨个引脚试就行了 方法二 使用万用表 1 指针表 1 前提是你的万用表最好是用3V以
  • Keil(MDK-ARM)的调试步骤

    Keil MDK ARM 的调试步骤 1 编译 调试 在线调试分类 软件在线调试和硬件在线调试 由于现在硬件成本 较便宜 般我们都使 硬件在线调试 也就是软件直接下载到芯 打开软件 程 gt 编译 gt 下载 gt 调试 如下图1 2 3
  • 计蒜客 挑战难题 第8题:字符串长度

    第8题 字符串长度 内存限制 10000 K 时间限制 1000 ms 在右侧我们给出了一个已经基本完成的程序 读入了一个字符串 调用了一个叫str len的函数来计算这个字符串的长度 并输出 聪明的你应该已经发现了 这个叫str len的
  • Mybaits中collection的用法详解

    作用 在Mybaits中collection标签是用来实现连表查询的 使用的场景 collection的使用场景为1 n和n n两种情况 添加的内容 使用collection的时候需要在类中添加关联集合 查询哪个类就在哪个类中添加 一 第一
  • linux c socket之异步IO

    cpp view plain copy File UDPEchoClient TimeOut c Author 云守护 include