Python之旅Day8 socket网络编程
socket网络编程
Socket是网络编程的一个抽象概念。通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协议类型即可。socket服务一般分为服务端和客户端;与此同时,socket服务有基本tcp和udp的两种版本类型
TCP类型
基础版socket服务
####服务端#### import socket phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#买手机 '''AF_INET:地址家族; SOCK_STREAM:TCP协议''' phone.bind(('127.0.0.1',8080))#插卡 phone.listen(5) #开机(监听) '''listen(5):等待客户端连接的最大连接数(可自定义数值)''' conn,addr=phone.accept()#接电话(3次握手建立连接) print('tcp的连接',conn) print('客户端的地址',addr) data = conn.recv(1024) #说话(收消息) print('from client msg: %s' %data) conn.send(data.upper()) #发消息 conn.close()#挂电话 phone.close()#关手机 ####客户端#### import socket client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) '''AF_INET:地址家族; SOCK_STREAM:TCP协议''' client.connect(('127.0.0.1',8080)) #拨通电话 client.send('hello'.encode('utf-8')) #客户端发消息 data = client.recv(1024) #客户端收消息 print(data) client.close() #关闭
循环版socket服务
####服务端#### import socket phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#买手机 '''AF_INET:地址家族; SOCK_STREAM:TCP协议''' phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) '''用来解决报错:ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。''' phone.bind(('127.0.0.1',8080))#插卡 phone.listen(5) #开机(监听) '''listen(5):等待客户端连接的最大连接数(可自定义数值)''' while True: #链接循环 conn,addr=phone.accept()#接电话(3次握手建立连接) print('client: ',addr) while True: #通讯循环 try: data = conn.recv(1024) #说话(收消息) if not data:break #针对Linux,客户端断开链接的异常处理 print('from client msg: %s' %data) conn.send(data.upper()) #发消息 except Exception: #异常捕捉 break conn.close()#挂电话 phone.close()#关手机 ####客户端#### import socket client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) '''AF_INET:地址家族; SOCK_STREAM:TCP协议''' client.connect(('127.0.0.1',8080)) #拨通电话 while True: msg = input('>>>: ') if not msg:continue client.send(msg.encode('utf-8')) #客户端发消息 data = client.recv(1024) #客户端收消息 print(data) client.close() #关闭
socketserver服务(可并发的socket)
####服务端#### import socketserver class FtpServer(socketserver.BaseRequestHandler): def handle(self): print(self.request) #conn print(self.client_address) while True: data = self.request.recv(1024) self.request.send(data.upper()) if __name__ == '__main__': s = socketserver.ThreadingTCPServer(('127.0.0.1',8080),FtpServer) s.serve_forever() #链接循环就有了 ####客户端1#### # import socket from socket import * client = socket(AF_INET,SOCK_STREAM) client.connect(('127.0.0.1',8080)) while True: msg = input('>>: ') client.send(msg.encode('utf-8')) data = client.recv(1024) print(data) ####客户端1#### # import socket from socket import * client = socket(AF_INET,SOCK_STREAM) client.connect(('127.0.0.1',8080)) while True: msg = input('>>: ') client.send(msg.encode('utf-8')) data = client.recv(1024) print(data) """ socketserver可以实现多并发,即一个服务端同时和多个客户端进行通信 """
远程执行
###远程执行命令-server端### import socket import subprocess import struct import json phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#买手机 '''AF_INET:地址家族; SOCK_STREAM:TCP协议''' phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) '''用来解决报错:ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。''' phone.bind(('127.0.0.1',8080))#插卡 phone.listen(5) #开机(监听) '''listen(5):等待客户端连接的最大连接数(可自定义数值)''' while True: #链接循环 conn,addr=phone.accept()#接电话(3次握手建立连接) print('client: ',addr) while True: #通讯循环 try: cmd = conn.recv(1024) #说话(收消息) if not cmd:break #针对Linux,客户端断开链接的异常处理 print('from client msg: %s' %cmd) res = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) err = res.stderr.read() if err: back_msg = err else: back_msg = res.stdout.read() #解决长度局限 #第一阶段:制作报头 head_dic = { 'data_size':len(back_msg) } head_json = json.dumps(head_dic) head_bytes = head_json.encode('utf-8') '''添加解决粘包代码''' # conn.send(struct.pack('i',len(back_msg))) #传数据的长度(有局限) #第二阶段:发送报头的长度 conn.send(struct.pack('i',len(head_bytes))) # conn.send(back_msg) # 第三阶段:发报头 conn.send(head_bytes) #第四阶段:发真实数据 conn.sendall(back_msg) except Exception: #异常捕捉 break conn.close()#挂电话 phone.close()#关手机 ###远程执行命令-client端### import socket import struct import json client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) client.connect(('127.0.0.1',8080)) while True: cmd= input('>>>: ').strip() if not cmd:continue client.send(cmd.encode('utf-8')) #解决粘包注释的改动部分(注释掉) # res=client.recv(1024) # print(res.decode('gbk')) '''通过定义传输数据文件大小来解决粘包''' # data = client.recv(4) # data_size=struct.unpack('i',data)[0] ###优化:接收头的长度 head = client.recv(4) head_size = struct.unpack('i',head)[0] ###收报头(根据报头长度) head_bytes = client.recv(head_size) head_json = head_bytes.decode('utf-8') head_dic= json.loads(head_json) data_size = head_dic['data_size'] #取真实数据 """大数据量传输(收真实数据)""" recv_size = 0 recv_bytes = b'' while recv_size < data_size: res=client.recv(1024) recv_bytes+=res recv_size+=len(res) print(recv_bytes.decode('gbk')) # res=client.recv(data_size) # print(res.decode('gbk'))
posted on 2017-07-26 15:10 py_chunwei 阅读(188) 评论(1) 编辑 收藏 举报