Linux套接字和I/O模型
目录
1. socket套接字的属性、地址和创建
2. 如何使用socket编写简单的同步阻塞的服务器/客户端
3. 理解Linux五种I/O模型
1.socket套接字
套接字是Linux系统提供的一种进程间通信的机制,通过socket套接字既可以满足同一计算机内部进程的通信,也可以满足不同计算机进程之间的通信。socket的使用与文件的操作使用文件描述符非常类似,操作套接字使用套接字描述符。套接字描述符使用文件描述符实现的,许多文件描述符的函数(如read和write)都可以处理套接字描述符。
1.1 套接字的创建
创建文件描述符使用open函数,创建套接字描述符使用socket函数,创建套接字的时候指定套接字的域、类型和协议三个参数。
socket函数原型:int socket(int domain,int type,int protocol)
1. 套接字的域指定通信中使用的介质。目前使用较多的是AF_INET(IPv4因特网域)、AF_INET6(IPv6因特网域)、AF_UNIX(Unix域,文件系统套接字)
2. 套接字的类型进一步确认通信的特征,在计算机网络中经常提及网络层的IP协议、传输层TCP/UDP协议。socket中通过指定套接字的类型指定面向连接和面向非链接的两种通信机制。
l SOCK_STREAM(流套接字)。流套接字提供的是有序、可靠、双向字节流的连接,整个通信过程维持一个连接,直到通信双方关闭连接。发送的数据可以确保不会丢失、复制、乱序到达。大的消息将被分片、传输、重组。这很像一个文件流,它接收大量的数据。然后以小数据块的形式写入底层磁盘。通过TCP/IP连接实现。
l SOCK_DGRAM(数据报套接字)。与流套接字相反,数据报套接字不建立和维持一个连接,它对可以发送的数据报的长度有限制。数据报作为一个单独的网络消息被传输,可能会丢失、复制或乱序到达、通过UDP/IP协议实现。
3. 套接字的协议protocol通常是0,指按照指定的域和套接字的类型选择默认的协议。
1.2 套接字地址
要想让通过socket调用创建的套接字可以被其它的进程调用,服务器程序必须给该套接字命名,也就是绑定一个固定的地址。例如AF_UNIX文件套接字会关联到一个文件系统的路径名、AF_INET域的套接字会关联到某个端口。不同域的套接字有自己对应的地址格式,客户端根据服务器端套接字的地址访问该套接字。
2. 使用socket编写简单的同步阻塞服务器/客户端
2.1简单socket服务器
1. 创建监听套接字,使用socket系统调用创建套接字,返回套接字描述符
2. 命名监听套接字,使用bind系统调用将套接字描述符绑定到某个固定的套接字地址
3. 使用listen系统调用创建监听套接字队列。为了能够在监听套接字上接收进入的连接,服务器程序必须创建一个队列来保存未处理的连接请求,Linux系统会对队列中可以容纳的未处理连接做出最大数目的限制,listen函数使用backlog参数限制。在套接字队列中,等待处理的连接不能超过backlog的指,再往后的连接将被拒绝,导致客户的连接请求失败。
int listen(int socket,int backlog)
4. 使用accept系统调用等待客户建立对监听套接字的连接。当客户端与服务端成功建立连接后,accept函数将创建一个新的套接字与该客户进行通信,accept函数返回的套接字类型与监听套接字的类型是完全一样的;如果服务器的套接字队列中没有未处理的连接时,accept将阻塞直到有客户连接为止。可以通过对套接字描述符设置O_NOBLOCK标志来改变这一行为。
5. 在新创建的套接字上进行读写操作
6. 关闭套接字
2.2 简单socket客户端
1. 根据服务器套接字的域、类型、协议,创建相应套接字
2. 如果处理的是面向连接的网络服务,在开始数据交换之前,需要在客户端和服务端之间通过connect函数建立一个连接。在connect中所指定的地址是想与之通信的服务器的地址。成功时,connect函数调用返回0,失败时返回-1。如果连接不能马上建立,connect调用将阻塞一段时间,一段时间后任然无法成功建立连接,连接将放弃,connect调用失败。和accept函数一样,connect函数也可以设置为非阻塞模式,那么在连接不能马上建立连接时,connect将会返回-1。
2.3 数据传输
前面讲过套接字描述符和文件描述符非常相似,并且套接字描述符是在文件描述符的基础上建立的。因此可以使用write和read函数来用作socket的数据的输出和输入。除此之外,针对socket的数据传输,linux提供了一些新的函数。
l write/read
l send/recv,在上面增加flag标志
l sendmsg/recvmsg
l sendto/recvfrom,数据报服务
三、Linux I/O模型
3.1 如何理解阻塞/非阻塞,同步/异步两组概念?
A: 阻塞与非阻塞指的是调用发起者者(线程)等待结果时的状态。阻塞调用是指调用结果返回之前,当前线程会被挂起,直到结果返回。非阻塞调用指不能立刻得到结果之前,线程不会阻塞等待,而是返回某种信息标示结果是否产生结果。
B: 同步和异步指的是通信双方的消息通信机制。同步指的是发起者(甲方)主动去获取乙方结果,在等待乙方产生结果的过程中,甲方可以处于阻塞状态,也可以是非阻塞状态。异步则相反,是由乙方通过状态、通知来通知甲方,或者通过回调函数处理这个调用。
举个例子:
我去书店买一本书,可以采用同步或者异步方式。在程序设计时也要先确定是采用同步还是异步方式。
1. 同步方式
A: 我去书店买一本书,立即买到了,或者没有就走,这就是非阻塞的(非阻塞方式)
B: 如果恰好书店没有,我就一直等到书店有了这本书买到了再走,这就是阻塞的,而排在我后面的人只有我买到了书后才能买书了(阻塞方式)
C: 如果恰好书店没有书,我就告诉书店老板,书来了告诉我一声我来取。然后我就去做别的事情(信号驱动)
2. 异步方式
我去书店买书,不管有没有书,告诉老板一声书来了,直接送到我家里。
反映在程序设计时,当用户进程调用系统调用。用户进程对应了我,内核对应书店老板,书对应资源,买书就是一个系统调用,其中内核拷贝数据到进程这个过程近似于老板送书到我家里。
3.2 Linux 五种I/O模型
1. 同步阻塞I/O
最常用的一个模型是同步阻塞I/O。在这个模型中,用户进程调用一个I/O系统调用send/recv函数,这会导致应用程序阻塞直到系统调用完成为止。
2. 同步非阻塞I/O
同步非阻塞I/O中,设备是以非阻塞形式打开的,这意味在这种模型中,设备是以非阻塞的形式打开的。这意味着 I/O 操作不会立即完成,read
操作可能会返回一个错误代码,说明这个命令不能立即满足(EAGAIN
或 EWOULDBLOCK
)。默认创建的socket是阻塞模式,可以参考“如何将socket设置为非阻塞模式”将socket设置为非阻塞模式,因为效率低很少使用非阻塞I/O。
3. 同步I/O多路复用
I/O多路复用就是通过一种机制,可以监听多个描述符,一个某个描述符就绪,一般就是读就绪或者写就绪,能够通知程序进行相应的操作,参考下面5个链接。
select:http://www.cnblogs.com/Anker/archive/2013/08/14/3258674.html
poll:http://www.cnblogs.com/Anker/archive/2013/08/15/3261006.html
epoll:http://www.cnblogs.com/Anker/archive/2013/08/17/3263780.html
4. 同步信号驱动I/O
首先允许套接字接口进行信号驱动I/O,并且安装信号处理函数,进程继续运行并不阻塞,当数据准备好时,进程会收到一个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据。
5. 异步I/O
以上四种I/O模型都是同步I/O,在Linux中只用使用特殊的AIO系统调用才是异步I/O模型。当一个异步系统调用发出后,调用者不能立即得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者的输入和输出操作。异步I/O的使用参考“”使用异步I/O大大提升应用程序的性能。下面有一副图比较5种I/O模型,将一个系统调用分为两部分,系统调用发起,数据从内核空间拷贝到用户空间。
参考资料:
4. select:http://www.cnblogs.com/Anker/archive/2013/08/14/3258674.html
5. poll:http://www.cnblogs.com/Anker/archive/2013/08/15/3261006.html
6. epoll:http://www.cnblogs.com/Anker/archive/2013/08/17/3263780.html
7. select、poll、epoll之间的区别总结[整理]
8. https://mmoaay.gitbooks.io/boost-asio-cpp-network-programming-chinese/content/Chapter1.html
Linux套接字和I/O模型的更多相关文章
- linux 套接字编程入门--Hello World
下述代码是linux套接字编程的入门代码.分为服务端和客户端源码. 服务端代码的主要流程是绑定ip地址和端口号建立套接字,等待客户端发起访问.接受客户端请求之后,向客户端发送字符串"hell ...
- Linux 套接字编程中的 5 个隐患(转)
本文转自IBM博文Linux 套接字编程中的 5 个隐患. “在异构环境中开发可靠的网络应用程序”. Socket API 是网络应用程序开发中实际应用的标准 API.尽管该 API 简单,但是开发新 ...
- 【 Linux 】Linux套接字简要说明
Linux套接字 源IP地址和目的IP地址以及源端口和目标端口号的组合称为套接字.其作用于标识客户端请求的服务器和服务. 套接字,支持TCP/IP的网络通信的基本操作单元,可以看做是不同主机之间 ...
- socket - Linux 套接字
总览 #include <sys/socket.h> mysocket = socket(int socket_family, int socket_type, int protocol) ...
- Linux 套接字通信笔记(一)
协议 TCP(传输控制协议),UDP(用户数据包协议)为传输层重要的两大协议,向上为HTTP提供底层协议,向下为数据链路层封装底层接口,乃是通信重中之重.TCP是面向流传输的协议,在编程中形象化为St ...
- 如何使用Linux套接字?
我们知道许多应用程序,例如E-mail.Web和即时通信都依靠网络才能实现.这些应用程序中的每一个都依赖一种特定的网络协议,但每个协议都使用相同的常规网络传输方法.许多人都没有意识到网络协 ...
- (转载)Linux 套接字编程中的 5 个隐患
在 4.2 BSD UNIX® 操作系统中首次引入,Sockets API 现在是任何操作系统的标准特性.事实上,很难找到一种不支持 Sockets API 的现代语言.该 API 相当简单,但新的开 ...
- Linux套接字编程
网络中的进程是如何通信的? 在网络中进程之间进行通信的时候,那么每个通信的进程必须知道它要和哪个计算机上的哪个进程通信.否则通信无从谈起!在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行 ...
- Linux 套接字编程中的 5 个隐患
http://www.ibm.com/developerworks/cn/linux/l-sockpit/ 在 4.2 BSD UNIX® 操作系统中首次引入,Sockets API 现在是任何操作系 ...
随机推荐
- mongodb 两小时入门
传统的计算机应用大多使用关系型数据库来存储数据,比如大家可能熟悉的MySql, Sqlite等等,它的特点是数据以表格(table)的形式储存起来的.数据库由一张张排列整齐的表格构成,就好像一个Exc ...
- springMVC ModelAndView 作用与功能解析 【转】
Spring mvc视图机制 所有的web应用的mvc框架都有它定位视图的方式.Spring提供了视图解析器供你在浏览器中显示模型数据,而不必被拘束在特定的视图技术上. Spring的控制器Contr ...
- 团队作业第四周(HCL盐酸队)——项目冲刺(第一篇)
任务认领情况: 1.坦克类实现:李密,卢泰佑 2.子弹类,线程类实现:黄国航 赖少勇 3.画笔类,地图的实现:陈舒标 黄宇航 明日任务安排: 今天在通过已经购买的GUI书籍的帮助下,已经实现了界面的 ...
- EBS xml publisher中文乱码
http://www.cnblogs.com/benio/archive/2011/11/22/2259313.html 由于本机环境问题,导致做的xml publisher报表跑不出来. 无法显 ...
- Win10下安装msi程序包时报2503、2502错误问题及其解决办法
Win10系统下安装TortoiseSvn.Node.js时(.msi后缀的安装文件),在点击安装时老是提示2503,2502错误,因此无法安装上. 搜索了下一般都提到是权限不够引起的该问题.但是右键 ...
- 使用ABP框架踩过的坑系列2
ABP中有很多惯例,如果使用得当,可以事半功倍,如果使用不当,也会有很大的麻烦,是否适当其实还是要看Need需求 ASP.NET Boilerplate (ABP) is an open source ...
- Extjs文件上传问题总结
本来文件上传是一个简单而常用的功能,但是,由于刚刚接触extjs,对extjs中的控件及其使用方法并不熟悉,导致本来一个很快就可以搞定的文件上传问题,弄了将近两天的时间.现将问题及解决办法发出来,供有 ...
- 数据库如何从SQL server转换到SQLite
我之前用的是SQL server数据库,但是客户那里觉得安装这个大的数据库比较卡,说是导致蓝屏了,硬往SQL server上赖,没有办法客户是上帝么,给他换个小点的数据库吧!考虑Access,不行这个 ...
- 获取form表单元素值的4种方式
<html><head><title></title><script type="text/javascript"> f ...
- ASP.NET Core获取客户端IP地址
1.在ConfigureServices注入IHttpContextAccessor // ASP.NET Core 2.1的注入方式 //services.AddHttpContextAccesso ...