Socket--selecct的用法

Select的用法(select是一个单线程)
s.bind(('127.0.0.1', 8888))
s.listen(5)
r_list = [s, ]
num = 0
while True:
    print(u"开始进入监听状态...")
    rl, wl, error = select.select(r_list, [], [], 10)#所有的过程都是单线程
要操作的对象都会放在rl里面的
    # 第一次执行循环体:客户端建立的连接的时候,rl和r_list分别是[s,]和[s,]
    #                  执行连接之后,r_list变为了[s,conn],建立连接会走if逻辑
    # 第二次执行循环体:有需要读取的时候,rl和r_list分别是[conn,]和[s,conn],执行else逻辑
    # 。。。。。如果客户端没有发送消息rl是[]
    ##第n次执行循环体:rl和r_list分别是[conn,]和[s,conn],执行else逻辑
    #简单来说rl会在建立连接后,添加socket对象,但是以后就不会在添加socket对象了,
    #因为建立连接的事件只会被select监听到一次。
    #然后select就一直监听已经建立的连接对象是否有数据发来了。当有异常的时候,会把链接对象从rl中删除掉。
    num += 1
    print(u'执行次数%s'% num)
    print("rl's length is %s" % len(rl))
    print("r_list length %s" % len(r_list))
    print([i for i in rl])
    for fd in rl:
        if fd == s:#客户端连接的时候会被触发一次
            conn, addr = fd.accept()#建立连接
            r_list.append(conn)#加入到监听列表里面
            msg = conn.recv(200)#收取从客户端来的数据
            conn.sendall(('first----%s' % msg.upper()).encode("utf-8"))#给客户端回复数据
        else:#客户端建立连接后发来了新的消息,会执行else分支
            try:
                msg = fd.recv(200)
                fd.sendall(msg.upper())#把收到的数据转换为大写后,发回给客户端
            except (ConnectionAbortedError, ConnectionResetError):
                r_list.remove(fd)
s.close()

Select的解释

fd_r_list, fd_w_list, fd_e_list = select.select(rlist, wlist, xlist, [timeout])

参数: 可接受四个参数(前三个必须)
rlist: 等待准备阅读
wlist: 等待准备写作(一般不使用)
xlist: 等待“例外情况”
timeout: 超时时间,表示多少秒监听一次,如果为None或者为空则阻塞直到至少有一个文件描述符已经准备好了。

s.bind(('127.0.0.1', 8888))
s.listen(5)
r_list = [s, ]
num = 0
while True:
    print(u"开始进入监听状态...")
    rl, wl, error = select.select(r_list, [], [], 10)
    # 第一次执行循环体:客户端建立的连接的时候,rl和r_list分别是[s,]和[s,]
    #                  执行连接之后,r_list变为了[s,conn],建立连接会走if逻辑
    # 第二次执行循环体:有需要读取的时候,rl和r_list分别是[conn,]和[s,conn],执行else逻辑
    # 。。。。。如果客户端没有发送消息rl是[]
    ##第n次执行循环体:rl和r_list分别是[conn,]和[s,conn],执行else逻辑
    #简单来说rl会在建立连接后,添加socket对象,但是以后就不会在添加socket对象了,
    #因为建立连接的事件只会被select监听到一次。
    #然后select就一直监听已经建立的连接对象是否有数据发来了。当有异常的时候,会把链接对象从rl中删除掉。
    num += 1
    print(u'执行次数%s'% num)
    print("rl's length is %s" % len(rl))
    print("r_list length %s" % len(r_list))
    print([i for i in rl])
    for fd in rl:
        if fd == s:#客户端连接的时候会被触发一次
            conn, addr = fd.accept()#建立连接
            r_list.append(conn)#加入到监听列表里面
            msg = conn.recv(200)#收取从客户端来的数据
            conn.sendall(('first----%s' % msg.upper()).encode("utf-8"))#给客户端回复数据
        else:#客户端建立连接后发来了新的消息,会执行else分支
            try:
                msg = fd.recv(200)
                fd.sendall(msg.upper())#把收到的数据转换为大写后,发回给客户端
            except (ConnectionAbortedError, ConnectionResetError):
                r_list.remove(fd)
s.close()


服务端的代码
r_list:select需要监听的文件对象。
开始的时候我初始化这个列表:r_list = [s, ] 
把socket放进去了。

1)开始执行:rl, wl, error = select.select(r_list, [], [], 10)
等待10秒,看看有没有人来建立连接,如果没有
2)代码继续执行从num += 1开始执行,然后执行到if,if和else并没有被触发
因为rl里面是空,什么都没有。
继续下一次循环,从1开始执行,如此反复。


如果有客户端进行连接了呢?开始代码向下执行:
rl从[]---->[s],
代码继续执行从num += 1开始执行,然后执行到if
if 的条件被触发了,客户端和server的连接被建立了。
    if fd == s:#客户端连接的时候会被触发一次
            conn, addr = fd.accept()#建立连接
            r_list.append(conn)#加入到监听列表里面
            msg = conn.recv(200)#收取从客户端来的数据
            conn.sendall(('first----%s' % msg.upper()).encode("utf-8"))#给客户端回复数据
结束当前循环,继续从1)开始。这个时候除了监控s对象有没有新建连接
请求外,conn也被监控看看客户端是否发来了数据。
如果没有新建链接也没有conn被发来数据,rl=[] -->if和else都不会被执行
继续下一次循环,从1)开始执行,如此反复。



r_list包含了conn对象(被监听),如果客户端发来数据,
rl, wl, error = select.select(r_list, [], [], 10)
rl=[] 变成了[conn],会触发else:操作,从连接中读取发来的数据,并
转换为大写之后返回给客户端

try:
                msg = fd.recv(200)
                fd.sendall(msg.upper())#把收到的数据转换为大写后,发回给客户端
            except (ConnectionAbortedError, ConnectionResetError):
                r_list.remove(fd)
继续下一次循环,从1)开始执行,如此反复。

15.3.客户端的情况 

rl:客户端既没有连接,有没有发送数据的情况下,rl一直是[]
只有在客户端有动作的时候,
它才从[]--->[s]或者[conn1]或者[conn1,conn2...]
1)新建连接的请求,s(socket对象)
2)已经建立连接后发送数据的连接对象conn对象(可能是一个也可能是多个。)

客户端的代码

import socket
flag = 1
s = socket.socket()
s.connect(('127.0.0.1', 8888))
while flag:
    input_msg = input('input>>>')
    if input_msg == '0':
        break
    s.sendall(input_msg.encode())
    msg = s.recv(1024)
    print(msg.decode())
s.close()

 

posted @ 2020-03-02 01:27  进阶的淑琴  阅读(445)  评论(0编辑  收藏  举报