网络编程6(IO)

Posted wanchenxi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络编程6(IO)相关的知识,希望对你有一定的参考价值。

IO  sock对象本质是文件描述符,什么是文件描述符,是一个非零的整数,内核区接受的数据,在用户拷贝完之后就没有了

IO多路复用比阻塞IO的好处是可以监听多个sock对象,能处理多个连接,IO多路复用全程阻塞,能实现并发现象,一定不是同时聊,没有开多线程多进程

什么是阻塞IO,(什么是非阻塞IO),主进程会一直卡住不能干其他事,知道对应的操作结束,非阻塞IO不会卡,

阻塞IO全程阻塞,非阻塞IO,copydaty时进程阻塞,IO多路复用全程阻塞;这三个是同步IO模型,只有第四个异步IO全程无阻塞,但是实现麻烦,全程由操作系统完成(waitdata copydata)

 同步IO只要两个过程(wait data,copy data)有一个是阻塞的就叫同步IO

同步:  阻塞IO  非阻塞IO  io多路复用(select epoll poll)
异步:  异步IO

IO模型有几个角色: 进程,操作系统(内核),IO都是进程的Io

http://www.cnblogs.com/yuanchenqi/articles/6755717.html

IO模型
进程如果有数据的交换,进程发系统调用进入内核态,内核态的数据cp到用户空间,分两个过程,wait for data ,copy data


阻塞IO




非阻塞IO

 IO多路复用

 


 IO multiplexing这个词可能有点陌生,但是如果我说select,epoll,大概就都能明白了。有些地方也称这种IO方式为event driven IO。我们都知道,select/epoll的好处就在于单个process就可以同时处理多个网络连接的IO。它的基本原理就是select/epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程。它的流程如图:

 

   当用户进程调用了select,那么整个进程会被block,而同时,kernel会“监视”所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用read操作,将数据从kernel拷贝到用户进程。
这个图和blocking IO的图其实并没有太大的不同,事实上,还更差一些。因为这里需要使用两个system call (select 和 recvfrom),而blocking IO只调用了一个system call (recvfrom)。但是,用select的优势在于它可以同时处理多个connection。(多说一句。所以,如果处理的连接数不是很高的话,使用select/epoll的web server不一定比使用multi-threading + blocking IO的web server性能更好,可能延迟还更大。select/epoll的优势并不是对于单个连接能处理得更快,而是在于能处理更多的连接。)
在IO multiplexing Model中,实际中,对于每一个socket,一般都设置成为non-blocking,但是,如上图所示,整个用户的process其实是一直被block的。只不过process是被select这个函数block,而不是被socket IO给block。

 

结论: select的优势在于可以处理多个连接,不适用于单个连接 

 

 

 

 

总结##################################################################################

IO就是进程有需要数据的时候才会产生IO系统调用,分两个阶段 1:wait for data;2: copy data

阻塞IO全程阻塞(进程在需要IO调用的时候,用户程序发动系统调用,从用户态转到内核态(内核态是操作系统管理,有操作硬件的权限)直到数据从内核缓存区cp到用户区,此时内核的数据直接清除),

非阻塞IO wait for data不阻塞,用户程序会隔一段时间就到内核区问问,数据准备好了没有,一次次的发起系统调用,直到有数据了,阻塞cp数据

IO多路复用:这个最大的改善是用户程序调用select函数发起系统调用阻塞等数据,等数据到了,用户进程发起系统调用cp数据,然后清除内核缓存中的数据,比IO阻塞多了个系统调用,下面的例子多个客户端聊天
就是及于此
1 阻塞IO: 全程阻塞 2 非阻塞IO:
优点:wait
for data时无阻塞 缺点:1 系统调用太多 2 数据不是实时接受的 两个阶段:wait for data:非阻塞 copy data :阻塞 3 IO多路复用(监听多个连接)
sock::sock <socket.socket fd=224, 
family=AddressFamily.AF_INET, 
type=SocketKind.SOCK_STREAM, 
proto=0, laddr=(\'127.0.0.1\', 8800)>
224就是文件打桩符
对于文件描述符(套接字对象):
1 是一个非零整数,不会变
2 收发数据的时候,对于接收端而言,数据先到内核空间,
然后copy到用户空间,同时,内核空间数据清除。

特点:1 全程(wait for data,copy)阻塞
      2 能监听多个文件描述符
      
      实现并发
       
4 异步IO

  全程无阻塞,


5 驱动信号

总结: 
同步:  阻塞IO  非阻塞IO  io多路复用
异步:  异步IO

 

#server端
#简单聊天,最大接受5个client排队,第一个连接后就进入while第二个,阻塞socket模块

import socket
import time

sock=socket.socket()

sock.bind(("127.0.0.1",8800))

sock.listen(5)

#sock.setblocking(False)

# while 1:
#     try:
#         conn,addr=sock.accept()   # 阻塞等待链接
#     except Exception as e:
#         print(e)
#         time.sleep(3)

# data=conn.recv(1024)
#
# print(data.decode("utf8"))

while 1:
    conn,addr=sock.accept()
    print("server working.......")
    while 1:

        data=conn.recv(1024)
        print(data.decode("utf8"))
        send_data=input(">>>")
        conn.send(send_data.encode("utf8"))

    conn.close()







#client端



import socket

sock=socket.socket()


sock.connect(("127.0.0.1",8800))

while 1:

     data=input("input>>>")
     sock.send(data.encode("utf8"))
     rece_data=sock.recv(1024)
     print(rece_data.decode("utf8"))

sock.close()

 

 

 

#给予select机制实现多客户端并发聊天   如果几个客户端先后发消息过来,监控的列表中conn几个会有变化,server端会吧有变化的conn for遍历一遍回消息再

#server端

#sock是客户来连接才有变化,conn是客户发消息才有变化,主要还是解决IO操作



import socket
import time

import select
sock=socket.socket()

sock.bind(("127.0.0.1",8800))

sock.listen(5)


sock.setblocking(False)
inputs=[sock,]

print("sock",sock)

while 1:
    r,w,e=select.select(inputs,[],[])  # select只监听有变化的套接字 inputs=[sock,conn1,conn2,conn3..] #开启select首先到这,
    print("r",r)
    for obj in r:   # 第一次 [sock,]  第二次(客户端发消息) #[conn1,]
        if obj==sock:#客户端第一次连接走这条路
            print(\'change\')
            conn,addr=obj.accept()
            inputs.append(conn)   #  inputs=[sock,conn]

        else:#客户端第二次发消息走这条路
            data=obj.recv(1024)
            print(data.decode("utf8"))
            send_data=input(">>>")
            obj.send(send_data.encode("utf8"))




#client 端
#跟上面的一样

 

以上是关于网络编程6(IO)的主要内容,如果未能解决你的问题,请参考以下文章

java缓冲字符字节输入输出流:java.io.BufferedReaderjava.io.BufferedWriterjava.io.BufferedInputStreamjava.io.(代码片段

VSCode自定义代码片段6——CSS选择器

UDP.6.重叠IO模型:完成例程

csharp C#代码片段 - 使类成为Singleton模式。 (C#4.0+)https://heiswayi.github.io/2016/simple-singleton-pattern-us

VSCode自定义代码片段——JS中的面向对象编程

找到我的自定义代码片段 Xcode 6?