Day8 -- socket network programming advanced, day8 -- socket
Socket: socketIt is to achieve data exchange between the server and the client. The server receives and sends data, and the client sends and receives data.Python3. This is because the client needs to convert to bytecode when sending a connection to the server, and also to bytecode when the server returns to the client.
As follows:
Server:
Import socket, osserver = socket. socket () server. bind ("localhost", 9999) server. listen () while True: conn, addr = server. accept () print ("new conn:", addr) while True: data = conn. recv (1024) if not data: print ("the client is disconnected! ") Break print (" execution command: ", data) pai_res = OS. popen (data. decode ()). read () print ("before send", len (FIG) if len (FIG) = 0: FIG = "cmd has no output ..... "conn. send (pai_res.encode ('utf-8') print ("send done") server. close ()
The above is the server side, using OS. popen () is used to process data, but only strings can be processed. Therefore, decode () must be in string format and then be converted to bytecode and encode () when sent ().
Client:
Import socketclient = socket. socket () client. connect ("localhost", 9999) while True: cmd = input (">> :"). strip () if len (cmd) = 0: continue client. send (cmd. encode ('utf-8') ''' sending on the server side is empty, and the client is the '''prop _res = client of the card master. recv (1024) print (pai_res.decode () client. close ()
Start the server first and then start the client, as shown below:
The server sends data:
>>: 1cmd has no output...>: dirbuild_server.py get_ip.py socket_server.py client creation process. pyclass_method.py lib s_server.py class method. pyclass method. py property. py static_method.py human. pyerror_handle.py s_client.py dynamic import. the content in the previous section of py is get_attr.py socket_client.py reflection. py >>:lsbuild_server.pyclass_method.pyclass method. pyerror_handle.pyget_attr.pyget_ip.pylibproperty. pys_client.pysocket_client.pysocket_server.pys_server.pystatic_method.py. py reflection. py client creation process. method of The py class. py human. content in the previous section of py
The client receives data:
New conn: ('2017. 0.0.1 ', 55324) execution command: B '1' before send 0 send done/bin/sh: 1: 1: not found execution command: B 'dir' before send 249 send done command: B 'ls' before send 219 send done
When the client gets stuck, it means that no data is sent from the server, becauseThe client cannot receive NULL data.,The server cannot receive NULL data either.. This will cause a choppy situation.
When receiving data, there will be a cache. When the cache is not satisfied, data will not be sent, and the client will not receive the data.
Due to the existence of the cache, the client sometimes receives incomplete data. How can this problem be avoided? The server is required to tell the client about the data size, and the client receives the data according to the data size.
The size of the data received by the client is as large as the size of the data received by the client:
Server:
Import socket, OS, timeserver = socket. socket () server. bind ("localhost", 9998) server. listen () while True: conn, addr = server. accept () print ("new conn:", addr) while True: data = conn. recv (1024) if not data: print ("the client is disconnected! ") Break print (" execution command: ", data)Performance_res=OS. popen (data. decode (). read ()Print ("before send", len (FIG) if len (FIG) = 0: FIG = "cmd has no output..." conn.Send (str (len (cmd_res). encode ('Utf-8'))# Size of the data sent first to the client's first send () to send dataTime. sleep (1) # Continuous data transmission will cause the phenomenon of sticking packets, so there must be a distinction, otherwise it is easy to stick packets, here let the program sleep for one second, first another receive and executeConn. send (pai_res.encode ('utf-8') # The second send () sends data print ("send done") server. close ()
On the server side, we calculate the size of the data sent to the client. First, we tell the client the size of the data, the size of the data received, and then send the real data to the client. When sending data, avoid sticking to the package. Because sending () is sent twice at the same time, it causes sticking to the package, so let the program sleep for one second, time. sleep (1) allows the client to receive data first, and then rereceives the data in one second, so that the package will not be glued.
The following figure shows how to stick the package;
>>: 1 command result size: B '22cmd has no output ..... 'traceback (most recent call last): File "/home/zhuzhu/Seventh Day/s_client.py", line 15, in <module> while using ed_size <int (using _res_size.decode (): ValueError:Invalid literalFor int () with base 10: '22cmd has no output .....'
When the client sends data, when the server returns the data, an error occurs because two send () sends data at the same time, resulting in a sticky packet. When two pieces of data are sent, they are connected together, resulting in sticking packets. The two data transmission links are linked together, and the reason for this is that the program runs too fast, the client receives the data very quickly, and the speed is before the next sending.
Client:
Import socketclient = socket. socket () client. connect ("localhost", 9998) while True: cmd = input (">> :"). strip () if len (cmd) = 0: continue client. send (cmd. encode ('utf-8') ''' sending on the server side is empty, and the client is the '''prop _res_size = client of the card master. recv (1024) # length of the command result received (sent by the server) print ("command result size:", pai_res_size) received_size = 0While received_size <int(Pai_res_size.decode ()):Data = client. recv (1024)Received_size+ =Len (data) # Each time the received message may be less than 1024, it must be determined by len ().Print (data. decode () print (received_size) else: print ("cmd res receive done ...... ", received_size) # pai_res = client. recv (1024) # print (pai_res.decode () client. close ()
In the client, we first receive the size of the data sent by the server, and then start to receive the data. When the data length is smaller than the receipt length, we continue to receive the data until no data is received.
In the client, the received data is not necessarily equal to the specified length. We also need to unify the format. We know that the length of Chinese characters is different from that of English characters. Chinese characters are composed of three bytes, because they are composed of two bytes.
Start the client first, and then start the server, as shown below:
Client sends data >>:1 command result size: B '22 'cmd has no output ..... 22cmd res receive done ...... 22>: ls command result size: B '275' build _ server. pyclass_method.pyclass method. pyerror_handle.pyget_attr.pyget_ip.pylibproperty. pys_client.pysocket_client.pysocket_server.pys_server.pystatic_method.py. py reflection. py client creation process. method of The py class. py human. py content in the previous section 275cmd res receive done ...... 275 >>>: dir command result size: B '000000' build _ server. py get_ip.py socket_server.py client creation process. pyclass_method.py lib s_server.py class method. pyclass method. py property. py static_method.py human. pyerror_handle.py s_client.py dynamic import. the content in the previous section of py is get_attr.py socket_client.py reflection. py305cmd res receive done ...... 305
As can be seen from the received data, if there is a Chinese character, the length of the received data is inconsistent, that is, because there are three Chinese characters, so they must be converted to a unified format, now, adjust the length of data sent by the server in bytes, as shown below:
Import socket, OS, timeserver = socket. socket () server. bind ("localhost", 9998) server. listen () while True: conn, addr = server. accept () print ("new conn:", addr) while True: data = conn. recv (1024) if not data: print ("the client is disconnected! ") Break print (" execution command: ", data) pai_res = OS. popen (data. decode ()). read () print ("before send", len (FIG) if len (FIG) = 0: FIG = "cmd has no output ..... "conn. send (str (len (Fig. Encode ('Utf-8 '))). Encode ('utf-8') # first send the data size to the client time. sleep (1) # continuous sending of data will cause the phenomenon of sticking packets, so there must be a distinction, otherwise it is easy to stick packets, here let the program sleep for one second, first receive and execute conn. send (pai_res.encode ('utf-8') print ("send done") server. close ()
Restart the server and start the client to send data as follows:
Client input command: >>: 1 command result size: B '22' cmd has no output ..... 22cmd res receive done ...... 22>: ls command result size: B '275' build _ server. pyclass_method.pyclass method. pyerror_handle.pyget_attr.pyget_ip.pylibproperty. pys_client.pysocket_client.pysocket_server.pys_server.pystatic_method.py. py reflection. py client creation process. method of The py class. py human. py content in the previous section 275cmd res receive done ...... 275 >>>: dir command result size: B '000000' build _ server. py get_ip.py socket_server.py client creation process. pyclass_method.py lib s_server.py class method. pyclass method. py property. py static_method.py human. pyerror_handle.py s_client.py dynamic import. the content in the previous section of py is get_attr.py socket_client.py reflection. py305cmd res receive done ...... 305
It can be seen from the above that after adjusting the sending length of the server side, the length of the received data is the same as the length of the client notified by the server. Therefore, when receiving and sending data, it is important to calculate the length in the bytecode mode in a unified format. In socket, the calculation length format is: bytecode, both sending and receiving data are in the form of bytecode.
Socket network programming is actually to send and receive data, only in the form of sending and receiving bytes, to unify the byte format, to be summoned in a timely manner, to inform the client of the size of the data. Then, the data is received by size. The program continues after receiving the message.
Stick package: the data sent twice is glued together.
How to solve the sticking package:
(1) sleep (), stay for one second, time. sleep (0.5 );
Server:
Import socket, OS, timeserver = socket. socket () server. bind ("localhost", 9999) server. listen () while True: conn, addr = server. accept () print ("new conn:", addr) while True: data = conn. recv (1024) if not data: print ("the client is disconnected! ") Break print (" execution command: ", data) pai_res = OS. popen (data. decode ()). read () print ("before send", len (FIG) if len (FIG) = 0: FIG = "cmd has no output ..... "conn. send (str (len (FIG ('utf-8 '))). encode ('utf-8') # first send the data size to the client time. sleep (1) # continuous sending of data will cause the phenomenon of sticking packets, so there must be a distinction, otherwise it is easy to stick packets, here let the program sleep for one second, first receive and execute conn. send (pai_res.encode ('utf-8') print ("send done") server. close ()
There is an interval between two data sending times on the server, which can avoid the situation where the data is sent in a sticky package. However, using sleep () is too low.
(2) After sending the data for the first time, receive the message sent from the client for the first time, and send the message for the second time. This will cut off the data transmission.
Server:
Import socket, OS, timeserver = socket. socket () server. bind ("localhost", 9998) server. listen () while True: conn, addr = server. accept () print ("new conn:", addr) while True: data = conn. recv (1024) if not data: print ("the client is disconnected! ") Break print (" execution command: ", data) pai_res = OS. popen (data. decode ()). read () print ("before send", len (FIG) if len (FIG) = 0: FIG = "cmd has no output ..... "conn. send (str (len (FIG ('utf-8 '))). encode ('utf-8') # first send the data size to the Client # time. sleep (1) # continuous sending of data will cause the phenomenon of sticking packets, so there must be a distinction, otherwise it is easy to stick packets, here let the program sleep for one second, first receive and executeClicent_ack= Conn. recv (1024) # Wait for the data to be received, so that the following send () is not executed for the time being, and the client's data size must be received for response. Wait to confirm print ("ack from client :", Clicent_ack)Conn. send (pai_res.encode ('utf-8') print ("send done") server. close ()
On the server side, to avoid sticking packets, add a confirmation that the data is successfully sent for the first time after sending the data twice, that is, receive the command for successfully sending the data, as shown above, conn. recv () does not actually have any function, that is, to cut off the execution time of the second sending, so that the second sending data will be executed after the first execution is completed;
Client:
Import socketclient = socket. socket () client. connect ("localhost", 9998) while True: cmd = input (">> :"). strip () if len (cmd) = 0: continue client. send (cmd. encode ('utf-8') ''' sending on the server side is empty, and the client is the '''prop _res_size = client of the card master. recv (1024) # length of the command result received (sent by the server) print ("command result size:", pai_res_size)Client. send ("Ready to receive, loser, you can send". encode ('utf-8'))Inclued_size = 0 while inclued_size <int (pai_res_size.decode (): data = client. recv (1024) received_size + = len (data) # each receipt may be less than 1024, so you must use len () to judge print (data. decode () print (received_size) else: print ("cmd res receive done ...... ", received_size) # pai_res = client. recv (1024) # print (pai_res.decode () client. close ()
On the client, after the data is received, the server sends the second command. The first command is the size of data to be sent, and the second command is to send data;
The above solves the problem of sticking packets.
In fact, the socket is synchronized when sending and data. To cut off the socket, you can only perform a successful verification. First, the socket is not allowed to be sent () after the first successful sending, the verification is passed and the second execution is performed again.