服务端必须满足至少三点:
1.绑定一个固定的ip和port
2.一直对外提供服务,稳定运行
3.能够支持并发
通信循环
from socket import * server = socket(AF_INET, SOCK_STREAM) server.bind(('127.0.0.1', 8080)) server.listen(5) conn, client_addr = server.accept() print(client_addr) # 通信循环 while True: try: data = conn.recv(1024) if len(data) == 0:break # 针对linux系统 print('-->收到客户端的消息: ',data) conn.send(data.upper()) except ConnectionResetError: break conn.close() server.close()
from socket import * client = socket(AF_INET, SOCK_STREAM) client.connect(('127.0.0.1', 8080)) # 通信循环 while True: msg=input('>>: ').strip() client.send(msg.encode('utf-8')) data=client.recv(1024) print(data) client.close()
链接循环
from socket import * server=socket(AF_INET,SOCK_STREAM) server.bind(('127.0.0.1',8081)) server.listen(5) #链接循环 while True: conn,client_addr=server.accept() print((client_addr)) #通信循环 while True: try: data=conn.recv(1024) if len(data)==0:break #针对linux系统 print('--->收到客户端消息:',data) conn.send(data.upper()) except ConnectionResetError: break conn.close() server.close()
from socket import * client=socket(AF_INET,SOCK_STREAM) client.connect(('127.0.0.1',8081)) #通信循环 while True: msg=input('>>:').strip() if len(msg)==0:continue client.send(msg.encode(('utf-8'))) data=client.recv(1024) print(data) client.close()
模拟ssh实现远程执行命令
from socket import * import subprocess server = socket(AF_INET, SOCK_STREAM) server.bind(('127.0.0.1', 8081)) server.listen(5) # 链接循环 while True: conn, client_addr = server.accept() print(client_addr) # 通信循环 while True: try: cmd = conn.recv(1024) if len(cmd) == 0: break # 针对linux系统 obj = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) stdout = obj.stdout.read() stderr = obj.stderr.read() print(len(stdout) + len(stderr)) conn.send(stdout + stderr) except ConnectionResetError: break conn.close() server.close()
from socket import * client=socket(AF_INET,SOCK_STREAM) client.connect('127.0..0.1',8081) while True: cmd=input('--->:').strip() if len(cmd)==0:continue client.send(cmd.encode('utf-8')) data=client.recv(1024000) print(data.decode('gbk')) client.close()
Struct模块
该模块可以把一个类型,如数字转换成bytes类型
import struct # obj1=struct.pack('i',13321111111) # print(obj1,len(obj1)) # res1=struct.unpack('i',obj1) # print(res1[0]) obj1=struct.pack('q',1332111111111) print(obj1,len(obj1))
模拟ssh实现远程执行命令(解决粘包问题终极版)
from socket import * import struct import json import subprocess server = socket(AF_INET, SOCK_STREAM) server.bind(('127.0.0.1', 8081)) server.listen(5) while True: conn, client_addr = server.accept() print(client_addr) while True: try: cmd = conn.recv(1024) if len(cmd) == 0: break obj = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) stdout = obj.stdout.read() stderr = obj.stderr.read() # 1.先制作报头 header_dic = { 'filename': 'a.txt', 'md5': 'sadsdadsasd12312321', 'total_size': len(stdout) + len(stderr) } header_json = json.dumps(header_dic) header_bytes = header_json.encode(('utf-8')) # 2.先发送4个bytes(包含报头的长度) conn.send(struct.pack(('i'), len(header_bytes))) # 3.再发送报头 conn.send(header_bytes) # 4.最后发送真实的数据 conn.send(stdout) conn.send(stderr) except ConnectionResetError: break conn.close() server.close()
from socket import * import json import struct client = socket(AF_INET, SOCK_STREAM) client.connect(('127.0.0.1', 8081)) while True: cmd = input('--->:').strip() if len(cmd) == 0: continue client.send(cmd.encode('utf-8')) # 1.先收4bytes,解出报头长度 header_size = struct.unpack('i', client.recv(4))[0] # 2.再接受报头,拿到header_dic header_bytes = client.recv(header_size) header_json = header_bytes.decode('utf-8') header_dic = json.loads(header_json) print(header_dic) total_size = header_dic['total_size'] # 3.接收真正的数据 cmd_res = b'' recv_size = 0 while recv_size < total_size: data = client.recv(1024) recv_size += len(data) cmd_res += data print(cmd_res.decode('gbk')) client.close()
两种情况下会发生粘包现象
1、发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据了很小,会合到一起,产生粘包)
#_*_coding:utf-8_*_ __author__ = 'Linhaifeng' from socket import * ip_port=('127.0.0.1',8080) tcp_socket_server=socket(AF_INET,SOCK_STREAM) tcp_socket_server.bind(ip_port) tcp_socket_server.listen(5) conn,addr=tcp_socket_server.accept() data1=conn.recv(10) data2=conn.recv(10) print('----->',data1.decode('utf-8')) print('----->',data2.decode('utf-8')) conn.close()
#_*_coding:utf-8_*_ __author__ = 'Linhaifeng' import socket BUFSIZE=1024 ip_port=('127.0.0.1',8080) s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) res=s.connect_ex(ip_port) s.send('hello'.encode('utf-8')) s.send('feng'.encode('utf-8'))
2、接收方不及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包)
#_*_coding:utf-8_*_ __author__ = 'Linhaifeng' from socket import * ip_port=('127.0.0.1',8080) tcp_socket_server=socket(AF_INET,SOCK_STREAM) tcp_socket_server.bind(ip_port) tcp_socket_server.listen(5) conn,addr=tcp_socket_server.accept() data1=conn.recv(2) #一次没有收完整 data2=conn.recv(10)#下次收的时候,会先取旧的数据,然后取新的 print('----->',data1.decode('utf-8')) print('----->',data2.decode('utf-8')) conn.close()
#_*_coding:utf-8_*_ __author__ = 'Linhaifeng' import socket BUFSIZE=1024 ip_port=('127.0.0.1',8080) s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) res=s.connect_ex(ip_port) s.send('hello feng'.encode('utf-8'))