Pythonsocket
Posted 素人渔芙2017
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Pythonsocket相关的知识,希望对你有一定的参考价值。
【server.py】终端cd到该目录下 输入文件名回车即可
#!/usr/bin/python3
#-*-coding:utf-8 -*-
"""
#练习1
import socket
import threading
sock = socket.socket()
sock.bind((\'127.0.0.1\',8889))
sock.listen(5)
def tcplink(conn,addr):
# sock.sendall(\'Hello Socket\'.encode(\'utf-8\'))
conn.send(bytes(\'Hello world\',encoding=\'utf-8\'))
conn.close()
while True:
conn, addr = sock.accept()
t = threading.Thread(target=tcplink,args=(conn,addr))
t.start()
#练习2: 和机器人聊天
import socketserver
class Myserver(socketserver.BaseRequestHandler):
def handle(self):
conn = self.request
conn.sendall((\'你好,我是机器人\').encode(\'utf-8\'))
while True:
ret_bytes = conn.recv(1024)
ret_str = ret_bytes.decode(\'utf-8\')
if ret_str == \'q\':
break
conn.sendall((ret_str + \'你好我好大家好\').encode(\'utf-8\'))
if __name__ == \'__main__\':
server = socketserver.ThreadingTCPServer((\'127.0.0.1\',8888),Myserver)
server.serve_forever()
#练习3 上传文件
import socket
sk = socket.socket()
sk.bind((\'127.0.0.1\',8887))
sk.listen()
while True:
conn,addr = sk.accept()
conn.sendall(\'欢迎光临我爱我家\'.encode(\'utf-8\'))
size = conn.recv(1024)
size_str = size.decode(\'utf-8\')
file_size = int(size_str)
conn.sendall(\'开始传送\'.encode(\'utf-8\'))
has_size = 0
f = open(\'db_new.JPG\',\'wb\')
while True:
if file_size == has_size:
break
date = conn.recv(1024)
f.write(date)
has_size += len(date)
f.close()
\'\'\'
参考:https://www.cnblogs.com/aylin/p/5572104.html “利用select实现伪同时处理多个Socket客户端请求”和“利用select实现伪同时处理多个Socket客户端读写分离”
下面两个例子我没跑通,只是想说明一下这个IO多路复用实现理论:SocketServer的ThreadingTCPServer之所以可以同时处理请求得益于 select 和 Threading 两个东西,其实本质上就是在服务器端为每一个客户端创建一个线程,当前线程用来处理对应客户端的请求,所以,可以支持同时n个客户端链接(长连接)
IO多路复用
I/O(input/output),即输入/输出端口。每个设备都会有一个专用的I/O地址,用来处理自己的输入输出信息首先什么是I/O:
I/O分为磁盘io和网络io,这里说的是网络io
IO多路复用:
I/O多路复用指:通过一种机制,可以监视多个描述符(socket),一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。
Linux
Linux中的 select,poll,epoll 都是IO多路复用的机制。
Linux下网络I/O使用socket套接字来通信,普通I/O模型只能监听一个socket,而I/O多路复用可同时监听多个socket.
I/O多路复用避免阻塞在io上,原本为多进程或多线程来接收多个连接的消息变为单进程或单线程保存多个socket的状态后轮询处理.
Python
Python中有一个select模块,其中提供了:select、poll、epoll三个方法,分别调用系统的 select,poll,epoll 从而实现IO多路复用。
1
2
3
4
5
6
7
8
9
10
11
Windows Python:
提供: select
Mac Python:
提供: select
Linux Python:
提供: select、poll、epoll
对于select模块操作的方法:
1
2
3
4
5
6
7
8
9
10
11
句柄列表11, 句柄列表22, 句柄列表33 = select.select(句柄序列1, 句柄序列2, 句柄序列3, 超时时间)
参数: 可接受四个参数(前三个必须)
返回值:三个列表
select方法用来监视文件句柄,如果句柄发生变化,则获取该句柄。
1、当 参数1 序列中的句柄发生可读时(accetp和read),则获取发生变化的句柄并添加到 返回值1 序列中
2、当 参数2 序列中含有句柄时,则将该序列中所有的句柄添加到 返回值2 序列中
3、当 参数3 序列中的句柄发生错误时,则将该发生错误的句柄添加到 返回值3 序列中
4、当 超时时间 未设置,则select会一直阻塞,直到监听的句柄发生变化
5、当 超时时间 = 1时,那么如果监听的句柄均无任何变化,则select会阻塞 1 秒,之后返回三个空列表,如果监听的句柄有变化,则直接执行。
\'\'\'
# 练习4 利用select 实现我伪同时处理多个Socket客户端请求
import select
import socket
sk1 = socket.socket()
sk1.bind((\'127.0.0.1\',8005))
sk1.listen()
inpu = [sk1,]
while True:
r_list,w_list,e_list = select.select(inpu,[],[],1)
for sk in r_list:
if sk == sk1:
conn,addr = sk.accept()
inpu.append(sk)
else:
try:
ret = sk.recv(1024).decode(\'utf-8\')
sk.sendall((ret + \'hao\').encode(\'utf-8\'))
except Exception as ex:
inpu.remove(sk)
#练习5 SocketServer模块的Fork方式 windows上不行,MAC上没试过
from socketserver import TCPServer, ForkingMixIn, StreamRequestHandler
import time
class Server(ForkingMixIn, TCPServer): # 自定义Server类
pass
class MyHandler(StreamRequestHandler):
def handle(self): # 重载handle函数
addr = self.request.getpeername()
\'Get connection from\', addr # 打印客户端地址
time.sleep(5) # 休眠5秒钟
self.wfile.write(\'This is a ForkingMixIn tcp socket server\') # 发送信息
host = \'\'
port = 1234
server = Server((host, port), MyHandler)
server.serve_forever() # 开始侦听并处理连接
"""
#更详细的,参考:http://blog.csdn.net/taiyang1987912/article/details/40376067
【client.py】 终端cd到该目录下 输入文件名回车即可
#!/usr/bin/python3
#-*-coding:utf-8 -*-
"""
#练习1
import socket
sock = socket.socket()
sock.connect((\'127.0.0.1\',8889))
#ret = sock.recv(1024).decode(\'utf-8\')
ret = str(sock.recv(1024),encoding=\'utf-8\')
print(ret)
sock.close()
#练习2 和机器人聊天
import socket
obj = socket.socket()
obj.connect((\'127.0.0.1\',8888))
ret_bytes = obj.recv(1024)
ret_str = ret_bytes.decode(\'utf-8\')
print(ret_str)
while True:
inp = input(\'你好请问您有什么问题? \\n >>>\')
if inp == \'q\':
obj.sendall(inp.encode(\'utf-8\'))
break
else:
obj.sendall(inp.encode(\'utf-8\'))
ret_bytes = obj.recv(1024)
ret_str = ret_bytes.decode(\'utf-8\')
print(ret_str)
#练习3 上传文件
import socket
import os
obj = socket.socket()
obj.connect((\'127.0.0.1\',8887))
ret_bytes = obj.recv(1024)
ret_str = ret_bytes.decode(\'utf-8\')
print(ret_str)
size = os.stat(\'yan.JPG\').st_size
obj.sendall(str(size).encode(\'utf-8\'))
obj.recv(1024)
with open(\'yan.jpg\',\'rb\') as f:
for line in f:
obj.sendall(line)
## 练习4 利用select 实现我伪同时处理多个Socket客户端请求
import socket
obj = socket.socket()
obj.connect((\'127.0.0.1\',8003))
while True:
inp = input(\'Please(q\\退出):\\n>>>\')
obj.sendall(inp.encode(\'utf-8\'))
if inp == \'q\':
break
ret = obj.recv(1024).decode(\'utf-8\')
print(ret)
#练习5 SocketServer模块的Fork方式 windows上不行,MAC上没试过
import socket
s = socket.socket() # 生成一个socket对象
server = socket.gethostname()
port = 1234
s.connect((server, port)) # 连接服务器
s.recv(1024) # 读取数据
s.close() # 关闭连接
"""
以上是关于Pythonsocket的主要内容,如果未能解决你的问题,请参考以下文章