SOCKET编程进阶
Posted it-scavenger
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SOCKET编程进阶相关的知识,希望对你有一定的参考价值。
socketserver
虽说用Python编写简单的网络程序很方便,但复杂一点的网络程序还是用现成的框架比较好。这样就可以专心事务逻辑,而不是套接字的各种细节。SocketServer模块简化了编写网络服务程序的任务。同时SocketServer模块也是Python标准库中很多服务器框架的基础。
socketserver模块可以简化网络服务器的编写,Python把网络服务抽象成两个主要的类,一个是Server类,用于处理连接相关的网络操作,另外一个则是RequestHandler类,用于处理数据相关的操作。并且提供两个MixIn 类,用于扩展 Server,实现多进程或多线程。
Server类
它包含了种五种server类,BaseServer(不直接对外服务)。TCPServer使用TCP协议,UDPServer使用UDP协议,还有两个不常使用的,即UnixStreamServer和UnixDatagramServer,这两个类仅仅在unix环境下有用(AF_unix)。
创建一个socketserver 至少分以下几步
1.首先,您必须创建一个请求处理类,继承BaseRequestHandlerclass类并且重 写父类的handle()方法,该方法将处理传入的请求。
2.其次,你必须实例化一个上面类型中的一个类(如TCPServer)传递服务器的地址和你上面创建的请求处理类 给这个TCPServer。
3.然后,调用handle_request()或者serve_forever()方法来处理一个或多个请求。
ser.handle_request() # 只处理一个请求,处理完就退出了
ser.serve_forever() # 处理多个请求,永远执行。
4.最后,调用server_close()关闭socket。
聊天并发实例
import socketserver
class MyServer(socketserver.BaseRequestHandler):
def handle(self):
print ("服务端启动...")
while True:
conn = self.request
print (self.client_address)
while True:
client_data=conn.recv(1024)
print (str(client_data,"utf8"))
print ("waiting...")
server_response=input(">>>")
conn.sendall(bytes(server_response,"utf8"))
# conn.sendall(client_data)
conn.close()
# print self.request,self.client_address,self.server
if __name__ == ‘__main__‘:
server = socketserver.ThreadingTCPServer((‘127.0.0.1‘,8098),MyServer)
server.serve_forever()
##########################################
import socket
ip_port = (‘127.0.0.1‘,8098)
sk = socket.socket()
sk.connect(ip_port)
print ("客户端启动:")
while True:
inp = input(‘>>>‘)
sk.sendall(bytes(inp,"utf8"))
server_response=sk.recv(1024)
print (str(server_response,"utf8"))
if inp == ‘exit‘:
break
sk.close()
解决大数据传送和粘包问题
粘包:相邻两次发送的数据粘在了一起
import socketserver
import subprocess
class Myserver(socketserver.BaseRequestHandler):
def handle(self):
while True:
conn=self.request
conn.sendall(bytes("欢迎登录","utf8"))
while True:
client_bytes=conn.recv(1024)
if not client_bytes:break
client_str=str(client_bytes,"utf8")
print(client_str)
command=client_str
result_str=subprocess.getoutput(command)
result_bytes = bytes(result_str,encoding=‘utf8‘)
info_str="info|%d"%len(result_bytes)
conn.sendall(bytes(info_str,"utf8"))
# conn.recv(1024)
conn.sendall(result_bytes)
conn.close()
if __name__=="__main__":
server=socketserver.ThreadingTCPServer(("127.0.0.1",9998),Myserver)
server.serve_forever()
#####################################client
import socket
ip_port=("127.0.0.1",9998)
sk=socket.socket()
sk.connect(ip_port)
print("客户端启动...")
print(str(sk.recv(1024),"utf8"))
while True:
inp=input("please input:").strip()
sk.sendall(bytes(inp,"utf8"))
basic_info_bytes=sk.recv(1024)
print(str(basic_info_bytes,"utf8"))
# sk.send(bytes(‘ok‘,‘utf8‘))
result_length=int(str(basic_info_bytes,"utf8").split("|")[1])
print(result_length)
has_received=0
content_bytes=bytes()
while has_received<result_length:
fetch_bytes=sk.recv(1024)
has_received+=len(fetch_bytes)
content_bytes+=fetch_bytes
cmd_result=str(content_bytes,"utf8")
print(cmd_result)
sk.close()
文件上传
import socket,os
ip_port=("127.0.0.1",8898)
sk=socket.socket()
sk.bind(ip_port)
sk.listen(5)
BASE_DIR=os.path.dirname(os.path.abspath(__file__))
while True:
print("waiting connect")
conn,addr=sk.accept()
flag = True
while flag:
client_bytes=conn.recv(1024)
client_str=str(client_bytes,"utf8")
func,file_byte_size,filename=client_str.split("|",2)
path=os.path.join(BASE_DIR,‘yuan‘,filename)
has_received=0
file_byte_size=int(file_byte_size)
f=open(path,"wb")
while has_received<file_byte_size:
data=conn.recv(1024)
f.write(data)
has_received+=len(data)
print("ending")
f.close()
#----------------------------------------------client
#----------------------------------------------
import socket
import re,os,sys
ip_port=("127.0.0.1",8898)
sk=socket.socket()
sk.connect(ip_port)
BASE_DIR=os.path.dirname(os.path.abspath(__file__))
print("客户端启动....")
while True:
inp=input("please input:")
if inp.startswith("post"):
method,local_path=inp.split("|",1)
local_path=os.path.join(BASE_DIR,local_path)
file_byte_size=os.stat(local_path).st_size
file_name=os.path.basename(local_path)
post_info="post|%s|%s"%(file_byte_size,file_name)
sk.sendall(bytes(post_info,"utf8"))
has_sent=0
file_obj=open(local_path,"rb")
while has_sent<file_byte_size:
data=file_obj.read(1024)
sk.sendall(data)
has_sent+=len(data)
file_obj.close()
print("上传成功")
注意:
1 纸条就是conn
2 一收一发(解决粘包的关键)
3 client_data=conn.recv(1024)
if 那边send一个空数据 这边recv为空,则recv继续阻塞,等待其他的数据。所以聊天的时候好好聊,别发空数据。
识别图中二维码,欢迎关注python宝典
以上是关于SOCKET编程进阶的主要内容,如果未能解决你的问题,请参考以下文章