多平台统一管理软件接口,如何实现多平台统一管理软件接口
284
2022-09-06
#yyds干货盘点#Python之TCP UDP
一、客户端/服务器架构
硬件C/S架构(打印机)软件C/S架构(web服务)server端要求:
力求一直提供服务要绑定一个唯一的地址,客户端可以明确的找到
二、基于tcp协议的简单套接字
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它时一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Scoket接口后面基于文件类型的套接字家族
AF_UNIXAF_INET(基于网络通信)
套接字的工作流程socket()模块函数用法importsocketsocket.socket(socket_family,socket_type,protocal=0)socket_family 可以是 AF_UNIX 或 AF_INET。socket_type 可以是 SOCK_STREAM 或 SOCK_DGRAM。protocol 一般不填,默认值为0。获取tcp/ip套接字 tcpSock =socket.socket(socket.AF_INET,socket.SOCK_STREAM) 获取udp/ip套接字 udpSock =socket.socket(socket.AF_INET,socket.SOCK_DGRAM) 由于socket模块中有太多的属性。我们在这里破例使用了'from module import *'语句。使用'from socket import *',我们就把socket模块里的所有属性都带到我们的命名空间里了,这样能 大幅减短我们的代码。例如tcpSock =socket(AF_INET, SOCK_STREAM)
服务端套接字函数客户端套接字函数公用用途的套接字函数代码示例
"""tcp服务端"""import socketIP_ADDR = ('127.0.0.1', 8001)# 创建服务器套接字sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 加入一条socket配置,重用ip和端口sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)# 把地址绑定到套接字sock.bind(IP_ADDR)# 监听链接sock.listen(5)while True: # 服务器无限循环 conn, address = sock.accept() # 接受客户端链接 print(address) while True: # 通信循环 msg = conn.recv(1024) # 对话(接收) conn.send(msg.upper()) # 对话(发送) conn.close()sock.close()"""tcp客户端"""import socketIP_ADDR = ('127.0.0.1', 8001)# 创建服务器套接字sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 尝试连接服务器sock.connect(IP_ADDR)while True: cmd = input('>>>').strip() sock.send(cmd.encode('utf-8')) # 对话(发送/接收) msg = sock.recv(1024) print(msg)sock.close()
6、关于套接字conn, address = phone.accept()中conn的内容
import socketphone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)phone.bind(('127.0.0.1', 8080))phone.listen(5)while True: conn, address = phone.accept() print(conn) print(address) while True: data = conn.recv(1024) print(data) conn.send(data.upper()) conn.close()conn.close()客户端输出数字后运行结果:
二、粘包的现象
只有TCP有粘包的现象,UDP永远不会粘包,粘包的问题是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据造成的TCP是面向连接的,面向流的,提供高可靠性服务。收发两端(客户端和服务器端)都要有--成对的socket,因此,发送端为了将多个发往接收端的包,更有效的发到对方UDP是无连接的,面向消息的,提供高效率服务,不会使用块的合并优化算法自制报头解决粘包问题
报头(真实数据的描述信息,数字不能编码成bstyp格式
三、多线程编程
基于tcp协议的socketserver
基于tcp的套接字,关键就是两个循环,一个链接循环,一个通信循环socketserver模块中分两大类:server类(解决链接问题)和request类(解决通信问题)server类request类继承关系
import socketserverclass FTPserver(socketserver.BaseRequestHandler): def handle(self): print('dasdas',self) print(self.request) # self.request = conn while True: # 通信循环 data = self.request.recv(1024) print(data) self.request.send(data.upper())if __name__ == '__main__': obj = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), FTPserver) obj.serve_forever() # 链接循环
分析socketserver源码
与通信有关的,BaseRequestHandler,StearmRequsetHandler,DatagramRequestHandler以下列代码为例:
ftpserver = socketserver.ThreadingTCPServer(('127.0.0.1',8080),FtpServer) ftpserver.server_forever()
源码分析总结:
基于TCP的socketserver我们自己定义的类中的
self.server即套接字对象self.request即一个链接self.client_address即客户端地址
基于UDP的socketserver我们自己定义的类中的
面向对象的网络编程
服务器端
""" 面向对象的网络编程服务器端 """import socketclassMyServer: address_family = socket.AF_INET# socket_type = socket.SOCK_STREAM listen_num =5receive_pack_size =1024coding ='utf-8'decoding ='gbk'def__init__(self, ip_address, bind_and_activate=True):self.ip_address = ip_addressself.socket = socket.socket(self.address_family,self.socket_type)ifbind_and_activate:try:self.server_bind()self.server_activate()except:self.server_close()defserver_bind(self):self.socket.bind(self.ip_address)self.ip_address =self.socket.getsockname()defserver_activate(self):self.socket.listen(self.listen_num)defserver_close(self):self.socket.close()defget_request(self):returnself.socket.accept() @staticmethoddefclose_request(request): request.close()defrun(self):whileTrue:self.conn,self.client_address =self.get_request() print('starting...')whileTrue:data =self.conn.recv(self.receive_pack_size)self.conn.send(data)server1 = MyServer(('127.0.0.1',8080))server1.run()
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~