如何同时将树莓派设置为服务器和客户端?

时间:2020-08-28 11:17:53

标签: python sockets raspberry-pi access-point

我同时将Raspberry用作服务器和客户端。 但是,我的RPI在作为客户端连接到另一台设备后没有启用服务器连接。要求是,RPI必须一次连接到多个设备。

使用以太网电缆的最小示例是:

Device A <-----ETH-----> RPI <-----ETH-----> Device B

因此,在上述配置中,首先将其作为客户端连接到设备B,设备A无法连接到RPI。如果我将其用作独立的服务器/客户端,则可以正常运行,但不能用作并行功能。没有错误消息,设备A只是没有连接到Raspberry。

请注意,我正在通过以太网转USB适配器连接设备A,它可以完美地用作独立服务器。我正在对树莓派上的每个设备使用多重处理。

感谢您的帮助。

我注意到在这种配置中,树莓充当了访问点(?)。 树莓派的功能是,它必须将传入的消息转发到另一台设备,以便每个设备都不知道彼此的端口或IP地址,只有PI知道。

所以我对树莓的简化代码是:

walkie_talkie.py

import socket

# socket.socket(socket.AF_INET, socket.SOCK_STREAM)

class walkie_talkie(socket.socket):
'''Inherits all functionalities of sockets.sockets
Use this class for connection using TCP/IP e.g. internet/ethernet

Example usage:

>>> from walkie_talkie import walkie_talkie
>>> wt = walkie_talkie()
>>> wt.BUFFERSIZE = 8
...
'''


def __init__(self):
    self.BUFFERSIZE = 8192
    self.STATE = None
    self.IP = None                              # Server IP
    self.PORT = 5000
    self.NUMBER_OF_UNACCEPTED_CONNECTIONS = 1
    self.bytestream = None
    self.PROTOCOL = socket.SOCK_STREAM # Using UDP: socket.SOCK_DGRAM
    super().__init__(socket.AF_INET, self.PROTOCOL)



def setup_server(self):
    print('****** SERVER SETUP ******\n'
          'TCP/IP: {}\n'
          'PORT: {}\n'
          'BUFFERSIZE: {}\n'
          'Acc. conn.: {}\n'
          '****** SERVER SETUP ******\n'.format(self.IP,
                                    self.PORT,
                                    self.BUFFERSIZE,
                                    self.NUMBER_OF_UNACCEPTED_CONNECTIONS))
    self.STATE = 'SERVER'
    self.bind((self.IP, self.PORT))
    self.listen(self.NUMBER_OF_UNACCEPTED_CONNECTIONS)
    self.CONN, self.ADDRESS = self.accept()


def setup_client(self):
    print('****** CLIENT SETUP ******\n'
          'TCP/IP: {}\n'
          'PORT: {}\n'
          'BUFFERSIZE: {}\n'
          'Acc. conn.: {}\n'
          '****** CLIENT SETUP ******\n'.format(self.IP,
                                    self.PORT,
                                    self.BUFFERSIZE,
                                    self.NUMBER_OF_UNACCEPTED_CONNECTIONS))
    self.STATE = 'CLIENT'
    #self.settimeout(10.0)
    self.connect((self.IP, self.PORT))
    #self.settimeout(None)
    print('Connected.')

由于我还必须通过同一设备的多个端口传输数据,因此我对每个通信隧道使用了多处理。

multiprocessing_rpi.py

import socket
from walkie_talkie import walkie_talkie
import multiprocessing
import time


def setup_alpha_watchdog(IP, PORT):
    ''' Creates an alpha watchdog

    :param str IP: Server IP on Raspberry to listen to
    :param int PORT: Server Port to open for Device A

    '''
    global BUFFERSIZE
    print('alpha Watchdog >> {} @ {}'.format(IP, PORT))
    alpha_watchdog = walkie_talkie()
    alpha_watchdog.IP = IP
    alpha_watchdog.PORT = PORT
    alpha_watchdog.BUFFERSIZE = BUFFERSIZE

    try:
        # Setup alpha watchdog and omega watchdog right afterwards
        alpha_watchdog.setup_server()
        omega_watchdog = setup_omega_watchdog(DEVICE_B_IP, PORT) # returns a walkie_talkie object as client

        superstream(alpha=alpha_watchdog,
                    omega=omega_watchdog)
    except Exception as watchdog_error:
        print('Error: ' + str(watchdog_error))
        exit()
    pass


def setup_omega_watchdog(IP, PORT):
    ''' Creates an omega watchdog 
    Description:
    omega watchdog takes data from alpha watchdog and pass them to the specified device
    If the connection is denied, abort both watchdogs.

    :param str IP: Server IP of Device B to connect to
    :param int PORT: Server Port on Device B to send data to

    '''
    global BUFFERSIZE
    print('omega Watchdog >> {} @ {}'.format(IP, PORT))
    watchdog = walkie_talkie()
    watchdog.IP = IP
    watchdog.PORT = PORT
    watchdog.BUFFERSIZE = BUFFERSIZE

    try:
        watchdog.setup_client()
    except Exception as watchdog_error:
        print('Error: ' + str(watchdog_error))
        exit()

    return watchdog


def superstream(alpha, omega):
    '''Streams data between the watchdogs on Request-Response scheme
    Description:
    After setting alpha & omega watchdogs, the communication takes place after incoming signal from alpha passed to omega.
    For example, the byte b'\x02\x00\x00\x00\xff\x00' coming from Device A will be passed to alpha watchdog
    and the raspberry will then pass this byte to the omega watchdog and finally to the Device B.

    :param object alpha: An alpha watchdog
    :param object omega: An omega watchdog
    '''

    while 1:
        try:
            # Get data coming from Device A and send it directly to Device B
            data_from_Device_A = alpha.CONN.recv(alpha.BUFFERSIZE)
            omega.send(data_from_Device_A )

            # Get response from Device B and send back to Device A
            RESPONSE= omega.recv(omega.BUFFERSIZE)
            alpha.CONN.send(RESPONSE)

        except Exception as e1:
            print('Error: ' + str(e1))
            break

    alpha.shutdown(2)
    alpha.close()
    omega.shutdown(2)
    omega.close()



if __name__ == '__main__':
    THIS_RPI_IP= '169.254.244.192'  # IP of raspberry, so Device A can connect to it
    DEVICE_B_IP = '192.xxx.....'  # Device B IP

    # Reserve ports correlating number of devices
    SERVER_PORTS = [5000,
                    # 5001,
                    # 5002,
                    # 5003,
                    # 5004,
                    5005]

    SERVER_IP = THIS_RPI_IP
    BUFFERSIZE = 8192
    PROCESS_LIST = []

    #For each port, setup a socket for clients
    for PORT in SERVER_PORTS:
        p = multiprocessing.Process(target=setup_alpha_watchdog, args=(THIS_RPI_IP, PORT,))
        PROCESS_LIST.append(p)
        p.start()

    for _ in PROCESS_LIST:
        _.join()

setup_alpha_watchdog中,我可以交换线路,在这里我首先作为客户端连接到设备B(成功!),然后收听设备A,但是我无法建立服务器作为设备A的连接。

0 个答案:

没有答案