1.五种I/O模型

1.阻塞I/O

2.非阻塞I/O

fcntl(fd, F_SETFL, flag|O_NONBLOCK);

忙等待,不推荐使用

3.I/O复用

4.信号驱动I/O

信号通知,有数据到来。应用进程通过信号处理程序中,调用recv函数,从内核空间拉到用户空间中。

5.异步I/O

信号接收到数据,推送到buf中。

2.select

int select (int nfds, fd_set* readfds, fd_set* writefds, fd_set* excepts, struct timeval* timeout);

void FD_CLR(int fd, fd_set* set);

int FD_ISSET(int fd, fd_set* set);

void FD_SET(int fd, fd_set* set);

void FD_ZERO(fd_set* set);

Select管理者

用select来管理多个I/O。一旦其中的一个或者多个I/O检测到我们所感兴趣的事件。

Select函数返回,返回值为检测到的事件个数

并且返回哪些I/O发生了事件

遍历这些事件,进而处理事件

param:

1.   读,写,异常集合中的文件描述符的最大值+1

2.   读集合

3.   写集合

4.   异常集合

5.   超时结构体

3.select改进回射客户端

(1)多个I/O,单进程处理

(2)服务端关闭与客户端的子进程,服务端等待到客户端read返回0;否则需要stdin输入。这样可以同时处理输入I/O,套接字I/O。

(3)标准输入I/O,网络I/O。同时检测这两种事件

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>#define ERR_EXIT(m) \do \{ \perror(m); \exit(EXIT_FAILURE); \}while(0)ssize_t readn(int fd, void* buf, size_t count) {size_t nleft = count;ssize_t nread;  //已经读了char* bufp = (char*)buf;while(nleft > 0) {if((nread = read(fd, bufp, nleft)) < 0) {if(errno == EINTR) continue;return -1;} else if (0 == nread) {return count - nleft;}bufp += nread;nleft -= nread;}return count;
}ssize_t writen(int fd, void* buf, size_t count) {size_t nleft = count;ssize_t nwrite;char* bufp = (char*)buf;while(nleft > 0) {if((nwrite = write(fd, bufp, nleft)) < 0) {    if(errno == EINTR)continue;return -1;} else if(0 == nwrite) {continue;}bufp += nwrite;nleft -= nwrite;}return count;
}ssize_t recv_peek(int sockfd, void* buf, size_t len) {while(1) {int ret = recv(sockfd, buf, len, MSG_PEEK);if(-1 == ret && errno == EINTR) continue;return ret;}
}//读取遇到\r\n截止,最大不能超过maxline
ssize_t readline(int sockfd, void* buf, size_t maxline) {int ret;int nread;char* bufp = (char*)buf;int nleft = maxline;while(1) {ret = recv_peek(sockfd, bufp, nleft);if(ret < 0) //信号中断 return ret;if(0 == ret)  //表示对方关闭套接口 return ret;nread = ret;int i;//该缓冲区中有\n,read读走for(i=0; i<nread; i++) {if(bufp[i] == '\n') {ret = readn(sockfd, bufp, i+1);  //包括\n都读走if(ret != i+1) exit(EXIT_FAILURE);return ret;}}//没有\n,read先读走这部分,然后bufp偏移if(nread > nleft) exit(EXIT_FAILURE);nleft -= nread;ret = readn(sockfd, bufp, nread); if(ret != nread) exit(EXIT_FAILURE);bufp += nread;    }return -1;
}void echo_cli(int sock) {
/*      char sendbuf[1024] = {0};  char recvbuf[1024] = {0};int n;while(fgets(sendbuf, sizeof(sendbuf), stdin) != NULL) {//将带有\n的buf发送过去//writen(sock, sendbuf, strlen(sendbuf));//TCP协议栈收到FIN报文 writen(sock, sendbuf, 1);//TCP协议栈收到RST报文writen(sock, sendbuf+1, strlen(sendbuf)-1);//第二次发送后,会产生SIGPIPE信号int ret = readline(sock, recvbuf, sizeof(recvbuf));if(-1 == ret) {ERR_EXIT("readline");} else if(0 == ret) {printf("client close\n");break;}fputs(recvbuf, stdout);memset(sendbuf, 0, sizeof(sendbuf));memset(recvbuf, 0, sizeof(recvbuf));}close(sock);
*/fd_set rset;FD_ZERO(&rset);int nready;int maxfd;int fd_stdin = fileno(stdin);if(fd_stdin > sock) maxfd = fd_stdin;elsemaxfd = sock;char sendbuf[1024] = {0};   char recvbuf[1024] = {0};while(1) {FD_SET(fd_stdin, &rset);FD_SET(sock, &rset);nready = select(maxfd+1, &rset, NULL, NULL, NULL);if(-1 == nready) ERR_EXIT("select");if(0 == nready) continue;if(FD_ISSET(sock, &rset)) {int ret = readline(sock, recvbuf, sizeof(recvbuf));if(-1 == ret) {ERR_EXIT("readline");} else if(0 == ret) {printf("server close\n");break;}fputs(recvbuf, stdout);memset(sendbuf, 0, sizeof(sendbuf));memset(recvbuf, 0, sizeof(recvbuf));} if(FD_ISSET(fd_stdin, &rset)) {if(fgets(sendbuf, sizeof(sendbuf), stdin) == NULL)break;writen(sock, sendbuf, strlen(sendbuf));memset(sendbuf, 0, sizeof(sendbuf));}}close(sock);
}void handle_sigpipe(int sig) {printf("recv a sig=%d\n", sig);
}int main () {//signal(SIGPIPE, handle_sigpipe);signal(SIGPIPE, SIG_IGN);  int sock;if(( sock= socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)ERR_EXIT("socket");sock = socket(PF_INET, SOCK_STREAM, 0);struct sockaddr_in servaddr;memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(5188);servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");if(connect(sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)ERR_EXIT("sockect");//获得本端ip,portstruct sockaddr_in localaddr;socklen_t addrlen= sizeof(localaddr);if(getsockname(sock,(struct sockaddr*)&localaddr, &addrlen) < 0)ERR_EXIT("getsockname");printf("ip=%s port=%d\n", inet_ntoa(localaddr.sin_addr), ntohs(localaddr.sin_port));struct sockaddr_in connaddr;socklen_t connlen = sizeof(connaddr);//通过getpeername得到对端addr,port[conn必须是已连接的套接字]getpeername(sock, (struct sockaddr*)&connaddr, &connlen);printf("ip=%s port=%d\n", inet_ntoa(connaddr.sin_addr), ntohs(connaddr.sin_port));echo_cli(sock);return 0;
}

socket编程(八)相关推荐

  1. python基础之socket编程

    阅读目录 一 客户端/服务器架构 二 osi七层 三 socket层 四 socket是什么 五 套接字发展史及分类 六 套接字工作流程 七 基于TCP的套接字 八 基于UDP的套接字 九 粘包现象 ...

  2. 你得学会并且学得会的Socket编程基础知识

    这一篇文章,我将图文并茂地介绍Socket编程的基础知识,我相信,如果你按照步骤做完实验,一定可以对Socket编程有更好地理解. 本文源代码,可以通过这里下载 http://files.cnblog ...

  3. python网络编程-socket编程

    一.服务端和客户端 BS架构 (腾讯通软件:server+client) CS架构 (web网站) C/S架构与socket的关系: 我们学习socket就是为了完成C/S架构的开发 二.OSI七层模 ...

  4. 你得学会并且学得会的Socket编程基础知识(转)

    这一篇文章,我将图文并茂地介绍Socket编程的基础知识,我相信,如果你按照步骤做完实验,一定可以对Socket编程有更好地理解. 本文源代码,可以通过这里下载 http://files.cnblog ...

  5. C++ Socket 编程

    介绍 Socket编程让你沮丧吗?从man pages中很难得到有用的信息吗?你想跟上时代去编Internet相关的程序,但是为你在调用 connect() 前的bind() 的结构而不知所措?等等- ...

  6. C语言SOCKET编程指南

    转载自:http://blog.sina.com.cn/s/blog_79b01f66010163q3.html 这篇文章完全可以作为c语言socket编程指南,无论在任何系统下.感谢作者fenglo ...

  7. 简单理解php的socket编程

    php的socket编程算是比较难以理解的东西吧,不过,我们只要理解socket几个函数之间的关系,以及它们所扮演的角色,那么理解起来应该不是很难了,在笔者看来,socket编程,其实就是建立一个网络 ...

  8. api有哪些 javasocket_Java Socket编程以及与Linux Socket API关系

    Socket 编程(基于Linux) Socket独立于具体协议的网络编程接口,在ISO模型中,主要位于会话层和传输层之间:在通用的计算机网络五层模型中,主要位于应用层和传输层之间. Linux So ...

  9. Socket基础八:网络IO模型的应用

    Socket基础八:网络IO模型的应用 作者:刘磊 2020.4.27 参考书目:<Windows网络编程>刘琰等著 一.实验目的 1)掌握WindowsI/O操作的基本原理. 2)掌握阻 ...

  10. Socket 编程实现基于 HTTP 协议的客户和服务

    目录 前言 研究背景及意义 研究内容及方法 研究要求与目标 相关知识点 HTTP协议 TCP协议 UDP协议 Socket编程技术 需求分析 Socket编程 Swing包 多线程的应用 功能设计 功 ...

最新文章

  1. 将SVN与BUG跟踪管理集成
  2. ThreadPoolExecuotor源码参考
  3. 华岗(1977-),男,博士,宁波市智慧城市规划标准发展研究院副研究员。
  4. java动态生成excel_java动态生成excel打包下载
  5. 软件测试抛出异常,异常测试之异常注入初探
  6. kali 安装vmware 14 for linux 出现问题
  7. [IOS]NSUserDefaults读取和写入
  8. 凯撒密码(凯撒移位)
  9. 系统辨识与自适应控制matlab仿真下载,系统辨识与自适应控制MATLAB仿真 全部程序...
  10. EPLAN学习教程目录
  11. dspic c语言教程,轻松学PIC之数码管篇 PIC单片机学习系列教程
  12. Python-sympy计算问题入门-求极限
  13. 怎么把图片进行压缩?分享几种压缩图片的方法
  14. python pip安装报错_基于windows下pip安装python模块时报错总结
  15. phicomm虚拟服务器怎么设置方法,斐讯(PHICOMM)路由器设置步骤
  16. RAC环境报错ORA-00239: timeout waiting for control file enqueue排查
  17. react-router v6替换history.goBack()和goForward()
  18. ESP32开发学习 LVGL Littlevgl 使用文件系统
  19. 2020 9 17POJ青蛙约会
  20. 由标明空子树的先序遍历序列创建二叉树

热门文章

  1. Hibernate持久化对象的三种状态深入理解
  2. CentOS 6下SSH限制IP和用户登录
  3. 有关两个jar包中包含完全相同的包名和类名的加载问题
  4. 【转】计算机科学中最重要的32个算法
  5. 微软力挺Silverlight 反击美棒球赛用Flash直播
  6. Citrix XenDesktop 虚拟桌面 每用户/设备 许可手动释放
  7. (转)Windows 性能监视器工具-perfmon
  8. JS 统计函数执行时间
  9. js jquery 判断元素是否在数组内
  10. Linux下修改TomcatJVM内存大小