In this article, the example for you to share the python implementation of udp transfer pictures of the specific code for your reference, the specific content is as follows
The first step is to understand the mode of operation of UDP
For the server, first bind the IP and port, the local test can use 127.0.0.1 is the machine's proprietary IP, port number greater than 1024 is customized, so use a port number greater than 1024, and then receive the client data, processing, return
For the client, UDP does not need to establish a connection, but just sends regardless of whether it is received or not, so you can send information directly to the server's IP address and port number, and then wait for an answer.
Note that the transmission of data is a binary stream data, so we need to find ways to encode the data to be transmitted into a binary stream, and then decode it after passing it, here I used opencv to read the picture into numpy array format, and then encode it, transmit it, and then decode it after finally receiving it.
First of all, the transmission of the entire picture at once, the idea is to accept the parameter settings are very large, and the picture is relatively small, the realization is relatively simple
First is the server script, which implements the receive, display, and answer
udp_sever.py
# -*- coding: utf-8 -*- import socket import cv2 import numpy as np s = (socket.AF_INET, socket.SOCK_DGRAM) # Bind ports. (('127.0.0.1', 9999)) print('Bind UDP on 9999...') while True: # Receive data. data, addr = (400000) print('Received from %s:%s.' % addr) #Decode nparr = (data, np.uint8) #Decode to image numpy img_decode = (nparr, cv2.IMREAD_COLOR) ('result',img_decode) () reply = "get message!!!" (('utf-8'), addr) ()
Client-side script that implements send image, receive answer
udp_client.py
# -*- coding: utf-8 -*- import socket import cv2 import numpy as np s = (socket.AF_INET, socket.SOCK_DGRAM) img = ('/home/xbw/jupyter_notebook/') img_encode = ('.jpg', img)[1] data_encode = (img_encode) data = data_encode.tostring() # Send data. (data, ('127.0.0.1', 9999)) # Receive data. print((1024).decode('utf-8')) ()
To make it easier to understand put the code that converts an image to binary and back again
import numpy as np import cv2 img = ('') img_encode = ('.jpg', img)[1] data_encode = (img_encode) str_encode = data_encode.tostring() #print(str_encode) nparr = (str_encode, np.uint8) img_decode = (nparr, cv2.IMREAD_COLOR) ('result',img_decode) () ()
Batch transfer of pictures
After a long time finally know how to transfer images in batches, first of all, we need to know how long the images need to be transmitted to the memory, otherwise we do not know when to stop receiving, so we have to consider adding a file header, tell the server to accept how long the code stream.
The realization of the idea is that, first of all, the client should first send a file header, contains the length of the code stream, with a long int-type number, first with the packing, send it over, and then the cycle of sending pictures of the code stream can be
Then the server first receives the file header, confirms the length of the image stream, then receives the stream of the determined length in a loop, and finally decodes it into an image.
The realization code is as follows:
First the client script
udp_client.py
# -*- coding: utf-8 -*- import socket import cv2 import numpy as np import struct s = (socket.AF_INET, socket.SOCK_DGRAM) # Read the image, encoded into binary bytes format img = ('/home/xbw/jupyter_notebook/') img_encode = ('.jpg', img)[1] data_encode = (img_encode) data = data_encode.tostring() #Define file headers, packaged into structures fhead = ('l',len(data)) # Send headers. (fhead,('127.0.0.1', 9999)) # Cyclic sending of image streams for i in range(len(data)//1024+1): if 1024*(i+1)>len(data): (data[1024*i:], ('127.0.0.1', 9999)) else: (data[1024*i:1024*(i+1)], ('127.0.0.1', 9999)) # Receive answer data. print((1024).decode('utf-8')) #Close ()
Then the server receives
udp_sever.py
# -*- coding: utf-8 -*- import socket import cv2 import numpy as np import struct s = (socket.AF_INET, socket.SOCK_DGRAM) # Bind ports. (('127.0.0.1', 9999)) print('Bind UDP on 9999...') while True: # Receive the file header, the length of the file header is determined by the calcsize function, note that here recvfrom is to receive UDP messages, recv is to receive TCP messages fhead_size = ('l') buf,addr = (fhead_size) if buf: # Here the result is a tuple, so take out the values data_size = ('l',buf)[0] #Receive picture streams with stream length recvd_size = 0 data_total = b'' while not recvd_size == data_size: if data_size -recvd_size >1024: data,addr = (1024) recvd_size += len(data) else: data,addr = (1024) recvd_size = data_size data_total += data # data, addr = (400000) print('Received') # reply = 'Hello, %s!' % ('utf-8') # (('utf-8'), addr) # Decode the received stream into a numpy array to display the image nparr = (data_total, np.uint8) img_decode = (nparr, cv2.IMREAD_COLOR) ('result',img_decode) () #Answer reply = "get message!!!" (('utf-8'), addr) ()
------------------- dividing line ----------------
The above is the basic implementation, and after some study I finally grasped the essence of UDP transmission
The first step is to determine the operational mechanisms of the client and server
Client: first define a socket object, do not need to bind, and then specify the IP address and port to send a message, and then if you use the recvfrom will have been blocking waiting for an answer (this is very useful, the role is to ensure that the other side does receive, and then send a new message, do not have to consider the issue of frequency of sending), in front of the addition of a while True can be sent in a circular, if the Involving a very large message, you can split send, the trick is to first send a file header high-speed server to send the contents of how large (header here we recommend the use of stuct library, see the previous routine), and then send the file content, to ensure that the cycle of sending, because each time you send, the other side when sent once, such as 2048 bytes sent to the opposite side of the contents of the set of each time to receive 1024, then the rest of the 1024 will be thrown away. If 2048 bytes are sent, and the opposite party is set to receive 1024 at a time, then the remaining 1024 will be thrown away instead of waiting for the next time to continue to receive. There are also binary streams that are sent.The methods I've used so far to convert to streams are:Picture with opencv, first imencode into binary, and then into numpy, and then tostring. file header this, need to know exactly how much memory, so that the server can receive, with the stuct library, which pack, unpack, calcsize three functions is very good to use, send the data when the pack When you send the data to pack it will be able to send. lists, dictionaries and so on, as the content of the file, using the json, a little bit of everything, first converted to json type, and then encode encoded into binary can be taken to send.
Server:First define a socket object, bind the IP address and port, so that the client can find, and then wait to receive the message, after receiving the message to process the message, answer, with the client's recvfrom, to ensure that the frequency of reception is consistent, the server in order to ensure that the message is always received, there must be a while True, the received message is a binary stream, and therefore have to be decoded. The message received is a binary stream, so it should be decoded. For the above mentioned encoding mode decoding, in fact, is the reverse operation of the encoding mode: pictures, decoding with opencv, first, and then again (data, cv2.IMREAD_COLOR). For receiving the file header, here is a bit of skill, use to determine the length of the file header, and then only receive this length of the code stream, and then unpack out can be, here unpack is a tuple. For json, decoding is the first decode, and then can be, is the reverse operation of the above code.
And then a little higher-end operationThe same script, multi-process work, it is necessary to use the creation of multiple processes, the idea is to create multiple new servers, and then assigned to different processes, their IP addresses can be the same, the port number is not the same on the line, and then you can work in parallel in the same script, here is different from the TCP, because UDP does not need to establish a connection!
Then attached is the source code of my implementation, there are two processes in the server script, one receives the image from client 1 and the other receives the list from client 2
server (computer)
udp_server.py
# -*- coding: utf-8 -*- import socket import cv2 import numpy as np import struct import threading import json #Set IP address, two server port numbers dest_ip = '127.0.0.1' img_port = 9999 msg_port = 6666 # Server 1 processing, answer functions, receive image, display, answer def receive_img(rec_img): while True: # Receive data. fhead_size = ('l') buf,addr = rec_img.recvfrom(fhead_size) if buf: data_size = ('l',buf)[0] print(data_size) recvd_size = 0 data_total = b'' while not recvd_size == data_size: if data_size -recvd_size >1024: data,addr = rec_img.recvfrom(1024) recvd_size += len(data) else: data,addr = rec_img.recvfrom(1024) recvd_size = data_size data_total += data # data, addr = rec_img.recvfrom(400000) print('Received') # reply = 'Hello, %s!' % ('utf-8') # rec_img.sendto(('utf-8'), addr) nparr = (data_total, np.uint8) img_decode = (nparr, cv2.IMREAD_COLOR) ('result',img_decode) (100) reply = "get message!!!" rec_img.sendto(('utf-8'), addr) # () # Server 2 functions, receive message, output, answer def receive_msg(rec_msg): while True: msg_data ,msg_addr = rec_msg.recvfrom(1024) msg_str = msg_data.decode('utf-8') msg = (msg_str) print(msg) reply = 'get the msg' rec_msg.sendto(('utf-8'),msg_addr) rec_msg.close() # Main functions Create server, bind ports, create and run two processes, call the above two functions. def main(): #create sockets rec_img = (socket.AF_INET, socket.SOCK_DGRAM) rec_msg = (socket.AF_INET, socket.SOCK_DGRAM) #Bind local address ports rec_img.bind((dest_ip, img_port)) rec_msg.bind((dest_ip, msg_port)) # Create processes t_recimg = (target=receive_img, args=(rec_img,)) t_recmsg = (target=receive_msg, args=(rec_msg,)) # Start the process t_recimg.start() t_recmsg.start() print('The program is running normally!!!') if __name__ == '__main__': main()
Client 1
udp_client_1.py
# -*- coding: utf-8 -*- import socket import cv2 import numpy as np import struct s = (socket.AF_INET, socket.SOCK_DGRAM) cap = (0) #(3,320) #(4,240) while True: if (): flag, img = () # img = ('/home/xbw/jupyter_notebook/') img_encode = ('.jpg', img)[1] data_encode = (img_encode) data = data_encode.tostring() # Define the header of the document fhead = ('l',len(data)) # Send headers, data. (fhead,('127.0.0.1', 9999)) for i in range(len(data)//1024+1): if 1024*(i+1)>len(data): (data[1024*i:], ('127.0.0.1', 9999)) else: (data[1024*i:1024*(i+1)], ('127.0.0.1', 9999)) # Receive an answer. (1) print((1024).decode('utf-8')) ()
Client 2
udp_client_2.py
import socket import cv2 import numpy as np import struct import json import time #define sockets send_msg = (socket.AF_INET,socket.SOCK_DGRAM) # Set the destination IP address, port number target_ip = '127.0.0.1' target_port = 6666 #Send data, wait for answer while True: data = [0,0,0,1] data_str = (data) send_msg.sendto(data_str.encode(),(target_ip,target_port)) (0.01) print(send_msg.recv(1024).decode('utf-8'))
This is the whole content of this article.