前言

由于没有公网IP,实现非局域网的Socket通信极为困难,将Socket服务端部署在服务器上,实现多个客户端相互转发可解决。


提示:以下是本篇文章正文内容,下面案例可供参考

一、实验环境

云服务器:ubuntu18.4—-python3.6
客户端PC:windows10—python3.7
客户端TX2:ubuntu18.4—python3.6

二、实验步骤

1.服务器配置

1.注册购买服务器套餐,点击示例可查看到当前内外网的IP

2.安装VNC远程 配置安全组(不装桌面不配置VNC也可以):
[先安装桌面] (https://zhuanlan.zhihu.com/p/151314336)
[安装VNC](https://zhuanlan.zhihu.com/p/152044577)
VNC无法远程的解决办法,注意重启
注意 配置安全组 配置为允许访问所有端口,方便省事

运行在服务器BaiDuserver.py:

import socketserver  #支持多个客户端   无限发送

client_state = {'PC': 0,'TX2': 0} #PC和TX2的ip的对象
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
while True:
try:
self.data = self.request.recv(4096).strip()
receved_string=self.data.decode("utf-8")
if client_state['TX2']!=0 and client_state['PC']!=0 and len(receved_string)!=0 and receved_string!='AT+PCstart' and receved_string!='AT+TX2start':
client_state['TX2'].request.send('ok'.encode("utf-8"))
client_state['PC'].request.send(client_state['TX2'].data)

if receved_string=='AT+PCstart':
client_state['PC']=self
print("PC connected")
if client_state['TX2'] != 0 and client_state['PC'] != 0: #检测是否都连上了
client_state['TX2'].request.send('PCready'.encode("utf-8"))
client_state['PC'].request.send('TX2ready'.encode("utf-8"))
elif receved_string=='AT+TX2start':
client_state['TX2']=self
print("TX2 connected")
if client_state['TX2'] != 0 and client_state['PC'] != 0: #检测是否都连上了
client_state['TX2'].request.send('PCready'.encode("utf-8"))
client_state['PC'].request.send('TX2ready'.encode("utf-8"))
except Exception as e:
print("err:",e)
try:
client_state['TX2'].request.send('AT+disconnect'.encode("utf-8"))
except Exception as e:
print("TX2需要手动重连:",e)
try:
client_state['PC'].request.send('AT+disconnect'.encode("utf-8"))
except Exception as e:
print("PC需要手动重连:",e)
client_state['PC']=0
client_state['TX2']=0
break
if __name__ == "__main__":
HOST, PORT = '172.16.0.4', 8080 #172.16.0.4 localhost
server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()

2.客户端配置

PCclient.py:

import socket
import time
client = socket.socket()

def connect_server():
while True:
try:
client.connect(('106.13.47.79', 8080)) # 106.13.47.79 localhost
break
except Exception as e:
time.sleep(1)
print("服务器没开", e)
client.send('AT+PCstart'.encode("utf-8"))
print("等待TX2连接中...")

connect_server()
data = client.recv(1024).strip() # 设置收多少字节
if data.decode("utf-8")=='TX2ready':
print("开始接收...")
while True:
receved_string= client.recv(1024).decode("utf-8") #设置收多少字节
print("recv:",receved_string)
if receved_string == 'AT+disconnect':
client.send('AT+PCstart'.encode("utf-8"))
print("等待TX2连接中...")
data = client.recv(1024).strip() # 设置收多少字节
if data.decode("utf-8") == 'TX2ready':
print("开始接收...")

# f = open("test.txt", 'a', encoding="utf-8")
# f.write(receved_string)
# f.write("\n")
# f.close()
client.close()

TX2client.py:

import socket
import time

client = socket.socket()
def connect_server():
while True:
try:
client.connect(('106.13.47.79', 8080)) # 106.13.47.79 localhost
break
except Exception as e:
time.sleep(1)
print("服务器没开", e)
client.send('AT+TX2start'.encode("utf-8"))
print("等待PC连接中...")
connect_server()
data = client.recv(1024).strip() # 设置收多少字节
if data.decode("utf-8")=='PCready':
print("开始发送...")
send_num=0
while True:
try:
send_str='TX2test: %s'%(str(send_num))
client.send(send_str.encode("utf-8")) #转二进制并发送
print("send:",send_str)
receved_string = client.recv(1024).decode("utf-8") #设置收多少字节 接收带数据会收到 ok
#print("recv:",receved_string)

if receved_string == 'AT+disconnect':
while True:
client.send('AT+TX2start'.encode("utf-8"))
print("等待PC连接中...")
data = client.recv(1024).strip() # 设置收多少字节
if data.decode("utf-8") == 'PCready':
print("开始发送...")
send_num = 0
break

time.sleep(1)
send_num=send_num+1
except Exception as e:
print("出错:", e)
client.send('AT+TX2start'.encode("utf-8"))
print("等待PC连接中...")
data = client.recv(1024).strip() # 设置收多少字节
print("error:",data)
if data.decode("utf-8") == 'PCready':
while True:
client.send('AT+TX2start'.encode("utf-8"))
print("等待PC连接中...")
data = client.recv(1024).strip() # 设置收多少字节
if data.decode("utf-8") == 'PCready':
print("开始发送...")
send_num = 0
break
client.close()

3.修改IP和端口

服务器的IP为服务器的内网IP,端口随意
客户端的IP为服务器的公网IP,端口同服务器的端口

三、效果展示

服务器启动后,当有设备连接会输出连接信息

PC客户端启动后,会输出等待TX2连接

TX2和PC同时启动后 TX2会输出一下信息,send后为发送的信息

PC端会接收到如下信息

PC主动断开连接,服务端和TX2客户端做了异常处理,当PC重新连接后恢复通信
image-20230613223300848

总结

  1. 上面实现了两个客户端利用百度云服务器上的服务端进行通信,多个客户端也是同理。
  2. 可以一以此为架构,做成更加、通用的业务,解决无公网IP的IP的各个设备无法通信问题

有任何疑问和想法,欢迎在评论区与我交流。