用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的主要内容,如果未能解决你的问题,请参考以下文章

第八章 socket网络编程:模拟ssh远程执行命令

39.IO多路复用(用select实现伪并发)

select 实现多路复用IO的server_socket

[Golang] 从零開始写Socket Server: 对长短连接的处理策略(模拟心跳)

socket编程模拟linux下的ssh代码实现

python_day socket 交互模拟ssh