链条传动

砥砺前行,不忘初心!

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

Client:

#!/usr/bin/env python
# -*- coding: utf-8 -*-


import socket

client = socket.socket()
client.connect(('127.0.0.1',9999))
# client.close()
while True:
    data = client.recv(1024)
    print(data)
    input('>>>')

 

Server:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''
IO多路复用实现伪并发


IO多路复用:select、poll、epoll
用来监听socket对象的内部是否变化了(变化是指:socket连接或收发消息)

服务器端的socket对象发生变化------->表示有新连接来了
服务器端有2个对象:server发生变化---->有新连接来了         server接收到新连接,生成conn:conn发生变化----->要收发消息了

'''

#服务端代码
import socket
import select

server = socket.socket()
server.bind(('127.0.0.1',9999))
server.listen(5)
#conn,address = server.accept()

# server1 = socket.socket()
# server1.bind(('127.0.0.1',9998))
# server1.listen(5)



while True:
    # 使用IO多路复用
    # 监听服务端的socket对象(server、server1等)的变化(可监听多个对象),对象发生变化时(有新连接来了),
    # 就将发生变化的对象写入r中(多个对象发生变化,就将变化的对象都写入r中---r是一个列表)
    #timeout:超时时间,监听等待1秒,如果没有变化就进行下一次循环
    #r是一个获取到新连接的对象列表
    r,w,e = select.select([server,],[],[],1)
    print('r:',r)
    #for循环能执行的前提是server发生变化(有客户端连接了,没有客户端连接r就是空的,即对象没发生变化)
    for s in r:
        print('s',s)
        #conn是客户端连接对象,这里没有进行监听就直接进行下一次循环了
        conn,addr = s.accept()
        conn.sendall(bytes('hello',encoding='utf-8'))
Server-1
#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''
IO多路复用实现伪并发


IO多路复用:select、poll、epoll
用来监听socket对象的内部是否变化了(变化是指:socket连接或收发消息)

服务器端的socket对象发生变化------->表示有新连接来了
服务器端有2个对象:server发生变化---->有新连接来了         server接收到新连接,生成conn:conn发生变化----->要收发消息了

'''

#服务端代码
import socket
import select

server = socket.socket()
server.bind(('127.0.0.1',9999))
server.listen(5)


while True:
    inp = [server,]
    # 使用IO多路复用,监听inp中的对象
    r,w,e = select.select(inp,[],[],1)
    print('r:',r)  #对象发生变化时,对象有可能是server变化(新连接)、也有可能是已有的客户端对象进行收发消息
    #r = [server,]
    #r = [conn,]

    for s in r:
        print('s',s)
        if s == server:   #表示新客户端连接
            #conn是客户端连接对象,要想后续继续监听该对象来进行和客户端的通信(收发消息)
            #可以把该对象也加入select多路复用,进行循环监听
            conn,addr = s.accept()
            inp.append(conn)
            conn.sendall(bytes('hello', encoding='utf-8'))
        else:   #客户端连接进行收发消息
            conn = s
            try:
                recv_data = conn.recv(1024)
                if not recv_data:
                    raise Exception('接收的数据为空,断开连接')
            except Exception as e:   #客户端断开连接,就将该客户端对象从inp中移除
                inp.remove(s)
Server-2
#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''
IO多路复用实现伪并发
select:支持跨平台、使用for循环来实现(效率不高)、监听个数有限制(最大监听1024个)
poll:使用for循环实现、没有监听个数限制
epoll:实现方法不同以上两种,效率更高
'''

#服务端代码
import socket
import select

server = socket.socket()
server.bind(('127.0.0.1',9999))
server.listen(5)


while True:
    inp = [server,]   #存放所有监听的对象
    out = []  #存放所有给服务端发过消息的客户端对象
    message = {}   #存放客户端给服务器发送的消息。例:conn:[消息1,消息2]
    # 使用IO多路复用,监听inp中的对象
    r,w,e = select.select(inp,out,[],1)   #r:发生变化的对象    w:发过消息的客户端对象
    print('r:',r)  #对象发生变化时,对象有可能是server变化(新连接)、也有可能是已有的客户端对象进行收发消息
    print('w:',w)   #客户端给服务端发送消息时,先不做处理,而是将该客户端添加到out中,等到循环时服务端再统一进行处理(读写分离)
    #r = [server,]
    #r = [conn,]

    for s in r:
        print('s',s)
        if s == server:   #表示新客户端连接
            #conn是客户端连接对象,要想后续继续监听该对象来进行和客户端的通信(收发消息)
            #可以把该对象也加入select多路复用,进行循环监听
            conn,addr = s.accept()
            inp.append(conn)   #将客户端对象添加到inp监听列表中
            message[conn] = []  #在message中创建一个key:value用来存放客户信息(conn:[])
            conn.sendall(bytes('hello', encoding='utf-8'))
        else:   #客户端连接进行收发消息
            conn = s
            try:
                recv_data = conn.recv(1024)
                if not recv_data:  #接收数据为空
                    raise Exception('接收的数据为空,断开连接')
                else:   #接收数据正常
                    out.append(conn)   #将该客户端对象加入out列表中
                    message[conn].append(recv_data)
            except Exception as e:   #客户端断开连接,就将该客户端对象从inp中移除,并将该对象所有的消息也一并移除
                inp.remove(s)
                del message[s]

    #循环w(w对应的是out列表),这里专门对发过消息的客户端进行回复
    for s in w:
        recv_data = message[s].pop()
        s.sendall(bytes('response:%s'%recv_data,encoding='utf-8'))
        out.remove(s)   #恢复完毕,将该客户端对象从out中移除
Server-3

 

posted on 2016-12-02 14:20  链条君  阅读(166)  评论(0编辑  收藏  举报