python实现同一个服务器对应多个客户端进行通信

本代码实现的功能为:服务器将客户端A发送的信息(json串)进行处理,并转发给客户端B。
客户端A的请求端口为19005,客户端B的请求端口为19004
具体实现功能代码如下:

1.客户端A向服务端发送信息(以json为例):
from socket import *

def client():
    # 创建socket
    tcp_client_socket = socket(AF_INET, SOCK_STREAM)

    # 目的信息
    server_ip = "127.0.0.1"   #服务端ip
    server_port = 19005     #端口

    # 链接服务器
    tcp_client_socket.connect((server_ip, server_port))
    
    #客户端向服务端发送json串
    data = 'S010712320039{"datas":[{"PN":"P1","PathID":"","StopID":"3","Type":2,"PositionX":1.000,"PositionY":0.000,"Speed":0.255,"CornerAngle":0}]}E'
    tcp_client_socket.send(data.encode('utf-8'))

    # 接收服务端返回数据,最大接收1024个字节
    recvData = tcp_client_socket.recv(1024)
    print('接收到的数据为:', recvData.decode('gbk'))

    # 关闭套接字
    tcp_client_socket.close()

if __name__ == "__main__":
    client()
2.服务端接收json串之后进行处理,转发给客户端B,代码如下:
#! /usr/bin/env python3
import json
from math import *
from socket import *

1)###欧拉角转四元素

def QuaterniondtoQuaternion(yaw, pitch, roll):   # yaw (Z), pitch (Y), roll (X)

    # // Abbreviations for the various angular functions
    cy = cos(yaw * 0.5)
    sy = sin(yaw * 0.5)
    cp = cos(pitch * 0.5)
    sp = sin(pitch * 0.5)
    cr = cos(roll * 0.5)
    sr = sin(roll * 0.5)

    q0 = cy * cp * cr + sy * sp * sr
    q1 = cy * cp * sr - sy * sp * cr
    q2 = sy * cp * sr + cy * sp * cr
    q3 = sy * cp * cr - cy * sp * sr
    
    q0 = round(q0, 3)
    q1 = round(q1, 3)
    q2 = round(q2, 3)
    q3 = round(q3, 3)
    
    #注意返回值的顺序
    return q1,q2,q3,q0
    

2)###接收客户端A的信息,进行数据处理,并返回校验数据

def server1(ip,port):

    # 创建socket
    tcp_server_socket = socket(AF_INET, SOCK_STREAM)
    #服务器ip与端口
    address = (ip, port)
    # 绑定
    tcp_server_socket.bind(address)
    #设置监听数.
    tcp_server_socket.listen(5)
    client_socket, clientAddr = tcp_server_socket.accept()
    # 接收对方发送过来的数据,和udp不同返回的只有数据
    recv_data = client_socket.recv(1024).decode('utf-8')  # 接收1024个字节,
  
    #处理接收的信息,截取{}中的信息,进行数据处理
    data = recv_data[13:-1]
    # print(data)  
    #json解析 str--->dict 先把字符串转换为字典
    data_dict = json.loads(data)
    # 只取字典data_dict['datas']的值
    dict_value = data_dict['datas'][0]
    # print(dict_value)
    global tup
    #需要转发的信息数据进行处理(符合目标格式)
    tup = (dict_value['PositionX'],dict_value['PositionY'],QuaterniondtoQuaternion(dict_value['CornerAngle'], 0, 0))
    print('接收的导航点为',tup)

    # 接收到数据,返回信息校验(向客户端A返回信息)
    data2 = 'T'+ recv_data[1:13].ljust(36,'0') + 'E'
    # print(data2)
    client_socket.send(data2.encode())
    
    #关闭连接
    client_socket.close()


3)#将处理之后的数据转发给客户端B

def server2(ip,port):

    tcp_server_socket = socket(AF_INET, SOCK_STREAM)
    address = (ip, port)
    tcp_server_socket.bind(address)
    tcp_server_socket.listen(2)
    client_socket, clientAddr = tcp_server_socket.accept()
    
    #调用server1, 客户端A连接的端口为19005
    server1('127.0.0.1',19005)  
    #判断是否接收到信息,如果不是空,则转发到客户端B
    if tup:
        client_socket.send(str(tup).encode())

    # 接收客户端B的返回信息
    # recv_data = client_socket.recv(1024).decode('utf-8')  # 接收1024个字节,
    # print('接收到的数据为:', recv_data.decode('utf-8'))

    # 关闭为这个客户端服务的套接字,只要关闭了,就意味着为不能再为这个客户端服务了,如果还需要服务,只能再次重新连接
    client_socket.close()
    

4)主函数运行

if __name__ == "__main__":

    while(1):  #服务端始终运行
        server2('127.0.0.1', 19004)  #客户端B请求端口为19004
        # time.sleep(20)   

在Ubuntu中运行可能存在问题:
python实现同一个服务器对应多个客户端进行通信_第1张图片

  1. 主要是因为防止服务端紧接着进行下一次链接,出现 OSError : [Errno 98] Address already in use. 出现这个错误的原因:在TCP/IP终止连接的第四次握手中,当最后的ACK回复发出后,有个2MSL的时间等待,MSL指一个片段在网络中最大的存活时间,这个时间一般是30秒,所以基本上过60秒后就可以重新连接!
    为什么要等待2MSL?是因为在最后发出ACK回复后,发送方不能确认ACK是否被另一端正常收到,如果另一端没有收到ACK回复的话,将会在1MSL后再次发送FIN片段。所以说发送方等待2MSL时间,也就是刚好它发ACK回复和对方发送FIN片段的时间,如果此时间内都没有再次收到FIN片段的话,发送方就假设对方已经正常接收到了ACK回复,此时它就会正常关闭连接!
  2. 解决:
    修改代码,tcp_server_socket2.bind(address2)等代码不要放在循环中,避免短时间内不断重复申请连接。
3.客户端B接收服务端信息,和客户端A的实现是一样的
from socket import *

def client():
    # 创建socket
    tcp_client_socket = socket(AF_INET, SOCK_STREAM)
    
    # 目的信息
    server_ip = "127.0.0.1"
    server_port = 19004
    
    # 链接服务器
    tcp_client_socket.connect((server_ip, server_port))

    while(1):
        ## 接收对方发送过来的数据,最大接收1024个字节
        recvData = tcp_client_socket.recv(1024)
        print('接收到的数据为:', recvData.decode('gbk'))
        if recvData:   #如果接收到数据不为空
            tcp_client_socket.send('1111'.encode('utf-8'))
            time.sleep(5)
        else:
            break

    # 关闭套接字
    tcp_client_socket.close()

if __name__ == "__main__":
    client()
4.运行结果展示

先运行服务端,再运行客户端B,最后运行客户端A
python实现同一个服务器对应多个客户端进行通信_第2张图片
如果发现任何疑问,欢迎留言指教。三克油~~

python实现TCP通信,参考链接:
Python实现TCP程序
Python实现TCP程序

你可能感兴趣的:(知识随手记,python)