tcp:属于长连接,与一个客户端进行连接了以后,其他的客户端要等待,要连接另外一个,必须优雅的断开前面这个客户端的连接.
允许地址重用:在bind IP地址和端口之前加上,# server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # 允许(IP地址和端口)地址重用
缓冲区
输入缓冲区 #recv
输出缓冲区 #send
粘包(tcp的两种粘包现象)
1 连续发送小的数据,并且每次发送之间的时间间隔很短(输出缓冲区:两个消息在缓冲区黏在一起了)
原因是TCP为了传输效率,做了一个优化算法(Nagle),减少连续的小包发送(因为每个消息被包裹以后,都会有两个过程:1 组包 2拆包)
2 第一次服务端发送的数据比我客户端设置的一次接收消息的大小要大,那么接收不完,第二次再接收的时候,就会将第一次剩余的消息接收到
粘包的根本原因是因为:双方不知道对方发送消息的大小
解决方案一:
发送消息之前,先计算要发送消息的长度,然后先将消息长度发送过去,对方给你回一个确认收到长度的信息,然后根据接收到的消息长度来修改自己一次接收消息的大小
这个过程多了一次交互
代码:
服务端
import socket import subprocess server = socket.socket() ip_port = ('192.168.15.142',8001) server.bind(ip_port) server.listen() conn,addr = server.accept() while 1: #来自客户端的指令 print('等待接受信息。。。') from_client_cmd = conn.recv(1024).decode('utf-8') print(from_client_cmd) sub_obj = subprocess.Popen( from_client_cmd, #客户端的指令 shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) #接受到的返回信息是bytes类型的,并且windows系统的默认编码为gbk server_cmd_msg = sub_obj.stdout.read() # server_cmd_err = sub_obj.stderr.read().decode('gbk') cmd_msg_len = str(len(server_cmd_msg)) print('指令返回的正确信息的长度>>>',cmd_msg_len) # print('指令返回的正确信息>>>',server_cmd_msg) # print('指令返回的错误信息...',server_cmd_err) conn.send(cmd_msg_len.encode('gbk')) from_client_ack = conn.recv(1024).decode('utf-8') print('from_client_ack',from_client_ack) if from_client_ack == 'ok': conn.send(server_cmd_msg) else: continue
客户端
import socket client = socket.socket() server_ip_port = ('192.168.15.142',8001) client.connect(server_ip_port) while 1: msg = input('请输入要执行的指令>>>') client.send(msg.encode('utf-8')) #先接收服务端要发送给我的信息的长度 from_server_msglen = int(client.recv(1024).decode('gbk')) print('..........',from_server_msglen) #给服务端回应一个收到了你的信息长度的确认信息 client.send('ok'.encode('utf-8')) #拿到信息长度后,将信息长度作为参数给了recv,recv就按照这个长度大小来接受服务端后面要给我发送的数据 from_server_stdout = client.recv(from_server_msglen).decode('gbk') print('收到的正确信息:', from_server_stdout) # from_server_error = client.recv(1024).decode('utf-8') # print('收到的错误信息:',from_server_error)