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: #异常捕捉breakconn.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:continueclient.send(msg.encode('utf-8')) #客户端发消息 data = client.recv(1024) #客户端收消息print(data)client.close() #关闭
socketserver服务(可并发的socket)
####服务端#### import socketserverclass FtpServer(socketserver.BaseRequestHandler):def handle(self):print(self.request) #connprint(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 jsonphone = 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 = errelse: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: #异常捕捉breakconn.close()#挂电话 phone.close()#关手机###远程执行命令-client端### import socket import struct import jsonclient = socket.socket(socket.AF_INET,socket.SOCK_STREAM) client.connect(('127.0.0.1',8080))while True:cmd= input('>>>: ').strip()if not cmd:continueclient.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 = 0recv_bytes = b''while recv_size < data_size:res=client.recv(1024)recv_bytes+=resrecv_size+=len(res)print(recv_bytes.decode('gbk'))# res=client.recv(data_size)# print(res.decode('gbk'))