感谢这位作者
https://blog.csdn.net/qq_36852276/article/details/90761122
1.理论基础
首先要了解UDP的工作模式
对于服务器,首先绑定IP和端口,本机测试的时候可以使用127.0.0.1是本机的专有IP,端口号 大于1024的是自定义的,所以用大于1024的端口号,然后接收客户端数据,处理,返回对于客户端,UDP不用建立连接,只管发送不管接收到没有,所以可以直接对服务器的IP地址和端口号发送信息,然后等待应答。
注意传输的数据是二进制流数据,所以要找方法把需要传输的数据编码成二进制码流,传过去之后再解码即可,这里我用到了opencv读取图片成numpy的array格式,然后编码,传输,最后接到之后再解码。
这里采用多个线程来完成图片与文件的获取
2 代码实现
#udp_sever.py
# -*- coding: utf-8 -*-
import socket
import cv2
import numpy as np
import struct
import threading
import json
#设置IP地址、两个服务器端口号
dest_ip = '127.0.0.1'
img_port = 9999
msg_port = 6666
#服务器1的处理、应答函数,接收图片、显示、应答
def receive_img(rec_img):
while True:
# 接收数据:
fhead_size = struct.calcsize('l')
buf,addr = rec_img.recvfrom(fhead_size)
if buf:
data_size = struct.unpack('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!' % data.decode('utf-8')
# rec_img.sendto(reply.encode('utf-8'), addr)
nparr = np.fromstring(data_total, np.uint8)
img_decode = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
cv2.imshow('result',img_decode)
cv2.waitKey(100)
reply = "get message!!!"
rec_img.sendto(reply.encode('utf-8'), addr)
# cv2.destroyAllWindows()
#服务器2函数,接收消息、输出、应答
def receive_msg(rec_msg):
while True:
msg_data ,msg_addr = rec_msg.recvfrom(1024)
msg_str = msg_data.decode('utf-8')
msg = json.loads(msg_str)
print(msg)
reply = 'get the msg'
rec_msg.sendto(reply.encode('utf-8'),msg_addr)
rec_msg.close()
#主函数 创建服务器、绑定端口、创建运行两个进程、调用上面两个函数
def main():
#创建套接字
rec_img = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
rec_msg = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#绑定本地地址端口
rec_img.bind((dest_ip, img_port))
rec_msg.bind((dest_ip, msg_port))
#创建进程
t_recimg = threading.Thread(target=receive_img, args=(rec_img,))
t_recmsg = threading.Thread(target=receive_msg, args=(rec_msg,))
#开始进程
t_recimg.start()
t_recmsg.start()
print('程序正常运行!!!')
if __name__ == '__main__':
main()
客户端1发送视频
udp_client_1.py
# -*- coding: utf-8 -*-
import socket
import cv2
import numpy as np
import struct
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
cap = cv2.VideoCapture(0)
#cap.set(3,320)
#cap.set(4,240)
while True:
if cap.isOpened():
flag, img = cap.read()
# img = cv2.imread('/home/xbw/jupyter_notebook/0.jpg')
img_encode = cv2.imencode('.jpg', img)[1]
data_encode = np.array(img_encode)
data = data_encode.tostring()
#定义文件头
fhead = struct.pack('l',len(data))
# 发送文件头、数据:
s.sendto(fhead,('127.0.0.1', 9999))
for i in range(len(data)//1024+1):
if 1024*(i+1)>len(data):
s.sendto(data[1024*i:], ('127.0.0.1', 9999))
else:
s.sendto(data[1024*i:1024*(i+1)], ('127.0.0.1', 9999))
# 接收应答:
cv2.waitKey(1)
print(s.recv(1024).decode('utf-8'))
s.close()
接下来文件的发送客户端
#udp_client_2.py
import socket
import cv2
import numpy as np
import struct
import json
import time
#定义套接字
send_msg = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
#设置目标IP地址、端口号
target_ip = '127.0.0.1'
target_port = 6666
#发送数据,等待应答
while True:
data = [0,0,0,1]
data_str = json.dumps(data)
send_msg.sendto(data_str.encode(),(target_ip,target_port))
time.sleep(0.01)
print(send_msg.recv(1024).decode('utf-8'))