用select模拟一个socket server

1, 必须在非阻塞模式下,才能实现IO的多路复用,否则一个卡住就都卡住了。(单线程下的多路复用)

先检测自己,现在没有客户端连进来,所以会卡住。

# 用select去模拟socket,实现单线程下的多路复用
import select
import socket
import queue

server = socket.socket()
server.bind(('localhost', 9000))
server.listen(1024)
server.setblocking(False)  # 设置为不阻塞,accept/recv没有数据都不阻塞,只会报错。

inputs = [server, ]  # 先检测自己,如果我有活动了,说明有客户端要连我了。
outputs = []
select.select(inputs, outputs, inputs)

# 第一个参数:需要检测哪些链接就放进来。操作系统发现100个里面有1个在活动,就会返回这100个。

# 第二个参数:

# 第三个参数:让操作系统检测100个的哪个有问题,就把有问题的返回。还是把100个放到这里。

server.accept() #没有链接也不阻塞,只是返回一个错误。

 运行结果:

C:abccdxdddOldboypython-3.5.2-embed-amd64python.exe C:/abccdxddd/Oldboy/Py_Exercise/Day10/ex3_Client.py

2. 客户端代码:

import socket
HOST = 'localhost'  # The remote host
PORT = 9000  # The same port as used by the server

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))

while True:
    msg = bytes(input(">>:"), encoding="utf8")
    s.sendall(msg)
    data = s.recv(1024)
    # print(data)
    print('Received', repr(data))  #repr:格式化输出

s.close()

 服务器端:

# 用select去模拟socket,实现单线程下的多路复用
import select
import socket
import queue

server = socket.socket()
server.bind(('localhost', 9000))
server.listen(1024)
server.setblocking(False)  # 设置为不阻塞,accept/recv没有数据都不阻塞,只会报错。

inputs = [server, ]  # 先检测自己,如果我有活动了,说明有客户端要连我了。
outputs = []
readable,writeable,exceptional=select.select(inputs, outputs, inputs)

# 第一个参数:需要检测哪些链接就放进来。操作系统发现100个里面有1个在活动,就会返回这100个。

# 第二个参数:

# 第三个参数:让操作系统检测100个的哪个有问题,就把有问题的返回。还是把100个放到这里。

print(readable,writeable,exceptional) #新来的链接会出现在readable里面,

server.accept() #没有链接也不阻塞,只是返回一个错误。

 运行结果:fd=240 文件描述符

C:abccdxdddOldboypython-3.5.2-embed-amd64python.exe C:/abccdxddd/Oldboy/Py_Exercise/Day10/ex3_Client.py
[<socket.socket fd=240, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000)>] [] []

Process finished with exit code 0

 3.

# 用select去模拟socket,实现单线程下的多路复用
import select
import socket
import queue

server = socket.socket()
server.bind(('localhost', 9000))
server.listen(1024)
server.setblocking(False)  # 设置为不阻塞,accept/recv没有数据都不阻塞,只会报错。

inputs = [server, ]  # 先检测自己,如果我有活动了,说明有客户端要连我了。
outputs = []
readable,writeable,exceptional=select.select(inputs, outputs, inputs)

# 第一个参数:需要检测哪些链接就放进来。操作系统发现100个里面有1个在活动,就会返回这100个。

# 第二个参数:

# 第三个参数:让操作系统检测100个的哪个有问题,就把有问题的返回。还是把100个放到这里。

print(readable,writeable,exceptional) #新来的链接会出现在readable里面,

for r in readable:
    conn,addr=server.accept() #没有链接也不阻塞,只是返回一个错误。
    print(conn,addr)

 客户端:

import socket
HOST = 'localhost'  # The remote host
PORT = 9000  # The same port as used by the server

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))

while True:
    msg = bytes(input(">>:"), encoding="utf8")
    s.sendall(msg)
    data = s.recv(1024)
    # print(data)
    print('Received', repr(data))  #repr:格式化输出

s.close()

运行结果:

C:abccdxdddOldboypython-3.5.2-embed-amd64python.exe C:abccdxdddOldboyPy_ExerciseDay10select_socket_server2.py
[<socket.socket fd=240, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000)>] [] []
<socket.socket fd=336, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 49587)> ('127.0.0.1', 49587)

Process finished with exit code 0

 至此链接已经建立。

4.最终版本

服务器端:

import select,socket
server=socket.socket()
server.bind(('localhost',9000))
server.listen(1024) #最多可以监听1024个
server.setblocking(False)
inputs=[server,]
outputs=[]
while True:
    readable,writeable,exceptional=select.select(inputs,outputs,inputs) #select帮着去检测这100个链接
    print(readable,writeable,exceptional)
    for r in readable:
        if r is server:
            conn,addr=server.accept()
            print('来了个新链接',addr)
            inputs.append(conn)
        else:
            data=r.recv(1024)
            print('收到数据',data)
            r.send(data)

 客户端:

import socket
s=socket.socket()
s.connect(('localhost',9000))
while True:
    msg=bytes(input(">>:"),encoding='utf8')
    s.sendall(msg)
    data=s.recv(1024)
    print('Received',repr(data))
s.close()

 运行结果:

C:abccdxdddOldboypython-3.5.2-embed-amd64python.exe C:/abccdxddd/Oldboy/Py_Exercise/Day10/select_socket_server2.py
[<socket.socket fd=232, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000)>] [] []
来了个新链接 ('127.0.0.1', 61118)
[<socket.socket fd=324, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 61118)>] [] []
收到数据 b'1'
[<socket.socket fd=324, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 61118)>] [] []
收到数据 b'2'
[<socket.socket fd=232, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000)>] [] []
来了个新链接 ('127.0.0.1', 61119)
[<socket.socket fd=328, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 61119)>] [] []
收到数据 b'3'
[<socket.socket fd=328, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 61119)>] [] []
收到数据 b'4'
[<socket.socket fd=324, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 61118)>] [] []
收到数据 b'7'
[<socket.socket fd=328, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 61119)>] [] []
收到数据 b'8'

 一个server端,两个client端

原文地址:https://www.cnblogs.com/momo8238/p/7384699.html