Socket服务器实现多个客户端通信

本文节选自我的博客:Socket 服务器实现多个客户端通信

  • 💖 作者简介:大家好,我是MilesChen,偏前端的全栈开发者。
  • 📝 CSDN主页:爱吃糖的猫🔥
  • 📣 我的博客:爱吃糖的猫
  • 📚 Github主页: MilesChen
  • 🎉 支持我:点赞👍+收藏⭐️+留言📝
  • 💬介绍:The mixture of WEB+DeepLearning+Iot+anything🍁

前言

由于没有公网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的各个设备无法通信问题

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

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在使用 socket 进行多个客户端通信时,可以采用多线程或者异步编程的方式。 使用多线程的方式,每个客户端连接到服务器后都会创建一个新的线程来处理该客户端的请求,这样不同的客户端之间的交互就不会互相干扰。下面是一个简单的示例代码: ```python import socket import threading def handle_client(conn, addr): while True: data = conn.recv(1024) if not data: break # 处理客户端发送的数据 conn.sendall(data) conn.close() def main(): host = '127.0.0.1' port = 5000 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind((host, port)) server_socket.listen() print(f"Server listening on {host}:{port}") while True: conn, addr = server_socket.accept() print(f"Connected by {addr}") # 创建新的线程来处理客户端请求 client_thread = threading.Thread(target=handle_client, args=(conn, addr)) client_thread.start() server_socket.close() if __name__ == '__main__': main() ``` 使用异步编程的方式,可以使用 Python 3.5 以上版本提供的 asyncio 模块,使用 async/await 关键字编写异步代码。下面是一个简单的示例代码: ```python import asyncio async def handle_client(reader, writer): while True: data = await reader.read(1024) if not data: break # 处理客户端发送的数据 writer.write(data) await writer.drain() writer.close() async def main(): host = '127.0.0.1' port = 5000 server = await asyncio.start_server(handle_client, host, port) print(f"Server listening on {host}:{port}") async with server: await server.serve_forever() if __name__ == '__main__': asyncio.run(main()) ``` 以上两种方式都可以实现多个客户端服务器之间的通信,具体使用哪种方式,取决于具体的需求和应用场景。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值