用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.最终版本
服务器端:
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:\abccdxddd\Oldboy\python-3.5.2-embed-amd64\python.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端

用select模拟一个socket server的更多相关文章
- 用select模拟一个socket server成型版2
1.字典队列测试 import queue msg_dic={} msg_dic[1]=queue.Queue() msg_dic[1].put('hello') msg_dic[1].put('bo ...
- 用select模拟一个socket server成型版
1.你往output里面放什么,下次循环就出什么. 2. 1.服务器端:实现了收和发的分开进行 import select,socket,queue server=socket.socket() s ...
- 用select (多路复用)模拟一个 socket server
需求:用select (多路复用)模拟一个 socket server.可以接收多并发. 1. 一开始是检测自己,如果我有活动了,就说明有客户端要连我了. #用select去模拟socket,实现单线 ...
- python利用select实现的Socket Server
# 利用python的select模块实现简单的Socket Sever #实现多用户访问,再次基础上可以实现FTP Server应用程序 # 发布目的,在于解决了客户端强行终止时,服务器端也跟着程序 ...
- C语言写了一个socket server端,适合windows和linux,用GCC编译运行通过
////////////////////////////////////////////////////////////////////////////////* gcc -Wall -o s1 s1 ...
- VFP 用 SPT 来发布一条 SELECT 到一个新的 SQL Server 表
为了发布一条 SQL SELECT 语句来创建一个新的 SQL Server 表, SQL Server 数据库的 select into/bulkcopy 选项必须是可用的. 在默认情况下, 对于 ...
- 面向连接的Socket Server的简单实现(简明易懂)
一.基本原理 有时候我们需要实现一个公共的模块,需要对多个其他的模块提供服务,最常用的方式就是实现一个Socket Server,接受客户的请求,并返回给客户结果. 这经常涉及到如果管理多个连接及如何 ...
- C#中自己动手创建一个Web Server(非Socket实现)
目录 介绍 Web Server在Web架构系统中的作用 Web Server与Web网站程序的交互 HTTPListener与Socket两种方式的差异 附带Demo源码概述 Demo效果截图 总结 ...
- [Golang] 从零開始写Socket Server(3): 对长、短连接的处理策略(模拟心跳)
通过前两章,我们成功是写出了一套凑合能用的Server和Client,并在二者之间实现了通过协议交流.这么一来,一个简易的socket通讯框架已经初具雏形了,那么我们接下来做的.就是想办法让这个框架更 ...
随机推荐
- 北京Uber优步司机奖励政策(12月11日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- mysql 常用语句使用
1.查询语句 SELECT * FROM table 2.更改语句 UPDATE table SET name = '123456' WHERE id = 100 3.插入语句 INSERT INTO ...
- centos7系统配置系统用户基于ssh的google身份验证
最近也是服务器各种被入侵,所以在安全上,要万分注意,特此记录,借助google的身份验证插件,获取动态验证码完成ssh登陆. OS: centos7 安装配置: 1. 安装epel源 yum -y i ...
- Git 与 GitHub
Git 这个年代,不会点Git真不行啦,少年别问问什么,在公司你就知道了~ Git是一个协同开发的工具,主要作用是进行版本控制,而且还能自动检测代码是否发生变化. 一. 安装 下载地址:https:/ ...
- SecureCRT 注册
http://download.csdn.net/download/xia2011214228/9952983 1.下载后解压到安装目录 2.输入自己要注册的:name company 后genera ...
- 150命令之线上查询及帮助命令 man hellp
150命令之线上查询及帮助命令 man 查询命令的帮助 man + 命令 NAME ls - list directory contents 命令+命令简单说明 SYNOPSIS ...
- rewrite or internal redirection cycle while processing nginx重定向报错
2018/05/07 15:03:42 [error] 762#0: *3 rewrite or internal redirection cycle while processing "/ ...
- ViewPager的简单使用说明
前提:工程中使用ViewPager,需要导入google提供的jar包(android-support-v4.jar). 要学习ViewPager的使用,建议直接看官方文档 Creating Swip ...
- C语言文件基本操作
1.用文本方式储存‘1’,‘0’,‘2’存入文件,然后用二进制方式从文件开头读出一个short型数据,并验证结果是否正确 #include<stdio.h> #include<str ...
- PMS
"通讯录--PMS"功能介绍及界面展示 首先是我们的登陆界面,以绿色为基调,配以繁星组成的星阵图,寓意为"散是满天星",希望每一位同学能在各自的生活中闪耀. 当 ...