Day8---Multi-threaded socket programming, TCP sticky packet processing

Source: Internet
Author: User
Tags ack

Review the procedure for socket programming:

Server side: 1 Declares the socket instance servers = Socket.socket () #括号里不写 The default address cluster uses af_inet that is IPv4 default type is sock. Sock_stream that is TCP/IP protocol 2 bind the address and Port server.bind ((' localhost ', 9999)) #ip地址和端口 tuple form, the port is an integer form 3 start listening Server.listen () 4 into the block Status, waiting for the connection to enter ######## from here, you can join the loop and loop the different connections so that you can accept the connection of the different clients ##### #while True: # Get the client IP address and port open a connection instance ############## from here Loop, so that you can loop to receive client data, but only to receive this one client ############ #客户端一断开, Conn received is all empty data, so enter a dead loop, so need an if judgment #while true:5 data = CONN.RECV (1024x768) #接收最大数据量, the official recommended maximum of 8192 write the whole data # Add the If judgment # if not data:# breakprint (data) 6 can send back data conn.send (Data.upper () ) #可以发送任何数据, here to turn the received into uppercase 7 Server.close () client: 1 Declaration Socket instance: client= Socket.socket () 2 connection server: Client.connect (' server_ip ', 9999)) #连接服务端的ip及端口 tuple form, the port is an integer form 3 data client.send #发送数据, any data # 4 receives the data returned by the server # Recv_data = CLIENT.RECV (1024)

Dynamic Import Module:

1 Practice: 2 1 lib AA 3 def Test (): 4     print ("hehe") 5 class C (object): 6     name = "Yang" 7     def __init__ (self): 8
   
    self.name = ' Shenyang '
    


9 lib test10 import importlib11 dd = importlib.import_module (' Lib.aa ') dd.test () print (DD. C (). Name)

Run:

Assertion:Correct judgment of the type of judgment

Judgment error

Same as if, but more concise, a sentence is OK

Continue with socket programming:

Although the client write is 1024 but not necessarily receive 1024 to receive a maximum of 1024 even if the server returns 100 bytes also received by the client received data, how much to the service side first send a number of data to send, the client received, began to receive data, until the specified size of the data, no longer received

Practice: Service-side
1 #!/usr/bin/env python3 2 # author:shen Yang 3 Import socket,os 4 ip_address = ' 192.168.16.10 ' 5 port = 8888 6 bind_addr ESS = (ip_address,port) 7 server = Socket.socket () 8 Server.bind (bind_address) 9 Server.listen ()     while True:11 Conn, addr = Server.accept () while     true:13         data = CONN.RECV (1024x768). Decode () if not         data:15             print ("Lost connection")             break17         Print ("This is from", addr,data)         cmd_res = Os.popen (data). Read ()         conn.send (str (LEN (cmd_ Res.encode (' Utf-8 '))). Encode (' Utf-8 '))         conn.send (Cmd_res.encode (' Utf-8 ')) Server.close ()

Client

1 #!/usr/bin/env python3 2 # author:shen Yang 3 Import socket 4 ip_address = ' 192.168.16.10 ' 5 # ip_address = ' 192.168.81 .133 ' 6 port = 8888 7 conn_address = (ip_address,port) 8 client = Socket.socket () 9 client.connect (conn_address) Ten while T rue:11     cmd = input (":>"). Encode (' Utf-8 ')     if len (cmd) = = 0:13         continue14     client.send (CMD) 15     cmd_size = Int (CLIENT.RECV (1024x768). Decode ())     print (cmd_size)     recov_size = 018     Recov_data = B ' 19 While     Recov_size < cmd_size:20         data = CLIENT.RECV (1024x768)         #print (data),         recov_size + = len (data )         #print (recov_size)         recov_data + = data25     else:26         print ("Finished, size", recov_size)         Print (Recov_data.decode ()) Client.close ()

The above code in Linux send will appear sticky packet client received is two data

The ultimate solution: Add the receive process to the server:

Client Plus Send process:

Practice: Ssh_server:
#!/usr/bin/env python3import socket,osip_address = ' 192.168.81.133 ' port = 8888bind_address = (ip_address,port) Server = Socket.socket () server.bind (bind_address) Server.listen () while true:    conn,addr = server.accept () while    true:        data = CONN.RECV (1024x768). Decode ()        if not data:            print ("Lost connection")            break        print ("This is from", Addr,data)        Cmd_res = Os.popen (data). Read ()        conn.send (str (LEN (cmd_res.encode (' Utf-8 '))). Encode (' Utf-8 '))        ack = CONN.RECV (1024x768). Decode ()        print (ACK)        conn.send (Cmd_res.encode (' Utf-8 ')) Server.close ()

Ssh_client

1 #!/usr/bin/env python3 2 Import socket 3 IP_Address = ' 192.168.81.133 ' 4 port = 8888 5 conn_address = (ip_address,port) 6 client = Socket.socket () 7 client.connect (conn_address) 8 while true:9     cmd = input (":>"). Encode (' Utf-8 '     ) If Len (cmd) = = 0:11         continue12     client.send (cmd)     cmd_size = Int (CLIENT.RECV (1024x768). Decode ())     Print (cmd_size)     client.send ("Received size". Encode (' Utf-8 '))     recov_size = 017     Recov_data = B "     Recov_size < cmd_size:19         data = CLIENT.RECV (1024x768)         #print (data)         recov_size + = len (data)         #print (recov_size)         recov_data + = Data24     else:25         print ("Finished, size", recov_size)-         print (recov_ Data.decode ()) Client.close ()

Upload file:Server-side logic:

Use Os.stat to get file details, send to Client

Another way to solve a sticky bag:

Only data of a specified size can never be glued to a packet

Practice: ftp_server.py
 1 #!/usr/bin/env python3 2 import socket,os,hashlib 3 ip_address = ' 192.168.81.133 ' 4 port = 8888 5 Bind_address = ( Ip_address,port) 6 server = Socket.socket () 7 server.bind (bind_address) 8 Server.listen () 9 while true:10 conn,addr =             Server.accept () One while true:12 print ("Waiting for new link") data = CONN.RECV (1024x768) if not data:15 Print ("Lost connection") Break17 print ("This is from", addr,data) Cmd,file_name = Data.decode (). Split () If Os.path.isfile (file_name): M = Hashlib.md5 () F = open (file_name, ' RB ') fi Le_size = Os.stat (file_name). St_size23 conn.send (str (file_size). Encode ()) ACK = CONN.RECV (1024x768). Deco De () Print ("Confirm:", ack)-f:27 m.update (line) + print ("Sending ..." ) Conn.send (line) F.close () to Conn.send (M.hexdigest (). Encode ()) print ("Send Complete" ) Server.close () 

ftp_client.py

 1 #!/usr/bin/env python3 2 import socket,hashlib 3 ip_address = ' 192.168.81.133 ' 4 port = 8888 5 Conn_address = (ip_addre Ss,port) 6 client = Socket.socket () 7 client.connect (conn_address) 8 while true:9 cmd = input ("Input your Cmd:>") . Strip () If Len (cmd) = = 0:11 Continue12 if Cmd.startswith ("get"): Client.send (Cmd.encode (' Utf-8 ')        ) file_name = Cmd.split () [1]15 server_response = Client.recv (1024x768) print ("Received response:", Server_response) 17 Client.send ("Received". Encode (' Utf-8 ')) + total_file_size = Int (Server_response.decode ()) Print ("Total", Total_ file_size) F = open (file_name + '. New ', ' WB ') recov_file_size = 022 m = HASHLIB.MD5 () all while R Ecov_file_size < total_file_size:24 if total_file_size-recov_file_size > 1024:25 size = 102           426 else:27 size = total_file_size-recov_file_size28 Print ("Last received", size) 29      #print ("Collect Data ...") 30     data = CLIENT.RECV (size) m.update (data) Recov_file_size + = len (data) f.write (data ) else:35 print ("Finished, size", recov_file_size,total_file_size) f.close () Notoginseng print ("Server-side Send the original MD5 ", Client.recv (1024x768). Decode ()) (" The Final MD5 ", M.hexdigest ())

Start learning SocketseverSocketsever is the most commonly used for the re-encapsulation of sockets is TCP and UDP

Inheritance Relationship:

To create a socket server step:

The following is the rewritten handle:

All client-side interactions with the client are instantiated with a single handle that is processed in handle.

Continue to modify handle add loop: and increase the judgment client exit:

Practice: Server:
1 Import Socketserver 2 class Mytcphandler (Socketserver. Baserequesthandler): 3     def handle (self): 4 while         true:5             try:6                 self.data = SELF.REQUEST.RECV (1024). Strip () 7                 print ("from", self.client_address) 8                 Print (self.data) 9                 self.request.send (Self.data.upper ()) 10             except Connectionreseterror as e:11                 print ("Client exit", E)                 break13 if __name__ = = "__main__": +     HOST, port= "localhost", 999915     server = Socketserver. TCPServer (Host,port), Mytcphandler)     server.serve_forever ()

Client

1 Import  Socket 2 client = Socket.socket () #声明socket类型 while generating socket connection object 3 #client. Connect ((' 192.168.16.200 ', 9999)) 4 Client.connect (' localhost ', 9999) 5 while true:6     msg = input (">>:"). Strip () 7     If Len (msg) = = 0:continue 8     Client.send (Msg.encode ("Utf-8")) 9     data = CLIENT.RECV (10240)     print ("recv:", Data.decode ()) 11 Client.close ()

The above does not support multiple concurrency until now, just write a one-on server

The following write multiple concurrency:Change only one place: 1 use multithreading to achieve

2 using a multi-process implementation: (not WinDOS, not supported, but Linux must work)

some ways to introduce Socketserver:1 return the file descriptor (the system calls itself, we generally do not use)

2 processing a single request is generally not available

3 Keep the request until you receive a definite shutdown (every 0.5 seconds to detect if I sent a shutdown signal)

Call Service_action () to clean up the garbage zombie process after receiving shutdown

4 tell Server_forever () close

5 Reuse of addresses, no waiting for TCP disconnects

Common sock serverserver = Socket.socket () #获得socket实例server. setsockopt (socket. Sol_socket, SOCKET. SO_REUSEADDR, 1) #重用地址

The three processes that are requested can be customized: 1 setup2 handle3 finish

Day8---Multi-threaded socket programming, TCP sticky packet processing

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.