20 Apr 18
1. Review of the previous lesson
1. TCP (a two-way connection is established) three-way handshake to establish a connection, and four waves to disconnect
Three-way handshake:
c----syn=1 seq=x--->s
s----ack=1+x syn=1 seq=y--->c
c----ack=1+y------->s
Four waves:
s------fin=1---------->c
c------>ack=1--------->s
c------>fin=1--------->s
s------>ack=1--------->c
127.0.0.1: local loopback address
Regardless of sending and receiving (send, receive), it is directly interacting with its own operating system, and the operating system then transfers the hardware to transmit the information to the other party's operating system.
Also based on the above reasons, there is no one-to-one correspondence between sending and receiving.
2、socket
Socket is an abstraction layer between the application layer and the transport layer, which specifically encapsulates the protocol below the transport layer into an interface for the application layer to use. The application only needs to call the socket interface or write the program according to the socket standard, and the written program naturally follows the tcp/ip protocol.
Second, the sticky package problem
TCP, also known as streaming protocol, has two characteristics:
a, like a steady stream of water
b. Optimize the transmission mechanism, and use the NAGLE algorithm to save data with a short time interval and a small amount of data into a wave
The above two characteristics lead to the sticky package problem
The idea of solving the problem of sticky packets is to know how much to send, and then how much to receive
Note: If you use time.sleep to solve, solve this end, there may be sticky packets on the other end
3. Solve the problem of sticky package (basic board)
a. struct module
1) Convert the integer number to the bytes type
2) The converted bytes are of fixed length
import struct
res=struct.pack('i',20332) # ‘i’ --integer
print (res, len (res))
res2=struct.unpack('i',res)
print(res2[0])
b. server
from socket import *
import subprocess
import struct
server = socket (AF_INET, SOCK_STREAM)
server.bind(('127.0.0.1',8080))
server.listen(5)
while True:
conn,client_addr=server.accept() #(connection object, client's ip and port)
print(client_addr)
while True:
try:
cmd=conn.recv(1024)
obj=subprocess.Popen(cmd.decode('utf-8'),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
stdout=obj.stdout.read()
stderr=obj.stderr.read()
# 1. Make a fixed-length header
total_size=len(stdout) + len(stderr)
header=struct.pack('i',total_size)
# 2. Send header
conn.send(header)
#3. Send real data
conn.send(stdout)
conn.send(stderr)
except ConnectionResetError:
break
conn.close()
server.close()
c. customer service
from socket import *
import struct
client = socket (AF_INET, SOCK_STREAM)
client.connect(('127.0.0.1',8080))
# print(client)
while True:
cmd=input('>>>: ').strip()
if not cmd:continue
client.send(cmd.encode('utf-8'))
#1. Receive fixed-length headers first
header=client.recv(4)
#2. Parse the header
total_size=struct.unpack('i',header)[0]
print(total_size) #1025
#3. According to the information in the header, receive real data
recv_size=0
res = b ''
while recv_size < total_size:
recv_data=client.recv(1024)
res+=recv_data
recv_size+=len(recv_data)
print(res.decode('gbk'))
client.close()
4. Solve the sticky package problem (Ultimate Edition)
a. struct module
import struct
import json
header_dic = {
'total_size': 3122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222121,
'md5': '123svsaef123sdfasdf',
'filename': 'a.txt'
}
header_json=json.dumps(header_dic)
# print(header_json,type(header_json))
header_bytes=header_json.encode('utf-8')
header_size=len(header_bytes)
print(header_size)
obj=struct.pack('i',header_size)
print (obj, len (obj))
b. server
from socket import *
import subprocess
import struct
import json
server = socket (AF_INET, SOCK_STREAM)
server.bind(('127.0.0.1',8080))
server.listen(5)
while True:
conn,client_addr=server.accept() #(connection object, client's ip and port)
print(client_addr)
while True:
try:
cmd=conn.recv(1024)
obj=subprocess.Popen(cmd.decode('utf-8'),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
stdout=obj.stdout.read()
stderr=obj.stderr.read()
# 1. Make the header
header_dic={
'total_size':len(stdout) + len(stderr),
'md5':'123svsaef123sdfasdf',
'filename':'a.txt'
}
header_json = json.dumps(header_dic)
header_bytes = header_json.encode('utf-8')
# 2. Send the length of the header first
header_size=len(header_bytes)
conn.send(struct.pack('i',header_size))
# 3. Send header
conn.send(header_bytes)
# 4. Send real data
conn.send(stdout)
conn.send(stderr)
except ConnectionResetError:
break
conn.close()
server.close()
c. Client
from socket import *
import struct
import json
client = socket (AF_INET, SOCK_STREAM)
client.connect(('127.0.0.1',8080))
# print(client)
while True:
cmd=input('>>>: ').strip()
if not cmd:continue
client.send(cmd.encode('utf-8'))
#1, the length of the first receive header
header_size=struct.unpack('i',client.recv(4))[0]
#2. Receive header
header_bytes=client.recv(header_size)
#3. Parse the header
header_json=header_bytes.decode('utf-8')
header_dic=json.loads(header_json)
print(header_dic)
total_size=header_dic[ 'total_size']
# print(total_size) #1025
#4. Receive real data according to the information in the header
recv_size=0
res = b ''
while recv_size < total_size:
recv_data=client.recv(1024)
res+=recv_data
recv_size+=len(recv_data)
print(res.decode('gbk'))
client.close()
5. Procedure for executing commands remotely
a. Client
from socket import *
client = socket (AF_INET, SOCK_STREAM)
client.connect(('127.0.0.1',8080))
# print(client)
while True:
cmd=input('>>>: ').strip()
if not cmd:continue
client.send(cmd.encode('utf-8'))
# print('has send')
res=client.recv(14744)
# print('has recv')
print (len (res))
print(res.decode('gbk'))
client.close()
b. server
from socket import *
import subprocess
server = socket (AF_INET, SOCK_STREAM)
server.bind(('127.0.0.1',8080))
server.listen(5)
while True:
conn,client_addr=server.accept() #(connection object, client's ip and port)
print(client_addr)
while True:
try:
cmd=conn.recv(1024)
obj=subprocess.Popen(cmd.decode('utf-8'),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
stdout=obj.stdout.read()
stderr=obj.stderr.read()
# Send the length of the data first
total_size=len(stdout) + len(stderr)
conn.send(total_size)
# send real data
conn.send(stdout)
conn.send(stderr)
except ConnectionResetError:
break
conn.close()
server.close()
#Interactive command or cd. . Generally, it needs to be on one machine, and remote control is not recommended. If required, do not execute directly, but simulate execution and send back the simulation results.