用select模拟一个socket server
Posted momo8238
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用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:\abccdxddd\Oldboy\python-3.5.2-embed-amd64\python.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:\abccdxddd\Oldboy\python-3.5.2-embed-amd64\python.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:\abccdxddd\Oldboy\python-3.5.2-embed-amd64\python.exe C:\abccdxddd\Oldboy\Py_Exercise\Day10\select_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.
以上是关于用select模拟一个socket server的主要内容,如果未能解决你的问题,请参考以下文章