我同时将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的连接。