1

I am using my Raspberry as a server and client at the same time. However, my RPI don't enable the connection as server after it connecting to another device as a client. The requirement is, the RPI has to connect to several devices at once.

The minimal example with ethernet cable would be:

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

So in the above configuration, first connecting it to Device B as a client, Device A can not be connected to the RPI. If I use it as a standalone server/client it works perfectly but as parallel functionality it doesnt work. There is no error message, Device A just doesnt connect to the Raspberry.

Note that, I am connecting device A via Ethernet-to-USB adapter and it works perfectly as standalone server. I am using multiprocessing for each device on the raspberry.

Any help is appreciated.

I note that in that configuration the raspberry acts as access point (?). The functionality of the raspberry is, that it has to forward the incoming messages to another device, so that each device doesn't know the port or IP address of each other, only the PI does.

So my simplified code for the raspberry is:

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.')

Since I also have to stream the data through multiple ports of the same devices, I am using multiprocessing for each communication tunnel.

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()

In setup_alpha_watchdog I can swap the line, where I first connect as client to device B (Successfully!) and then listen to device A, however I am not able to establish a connection as server to device A.

V.Hunon
  • 320
  • 3
  • 12
  • you cannot "listen to a server IP" : :`param str IP: Server IP on Raspberry to listen to` – snus74 Aug 28 '20 at 12:12
  • can you explicit the socket types, ex: device A (client) <--> PI server, PI client <----> device B (server) – snus74 Aug 28 '20 at 12:14
  • @snus74 All sockets were: socket.socket(socket.AF_INET, socket.SOCK_STREAM) - So internet sockets with TCP – V.Hunon Aug 31 '20 at 06:50
  • Hi, my question was if you can explicit which socket is a client and which one is a server in the entire system (PI + remote devices A and B) – snus74 Aug 31 '20 at 07:02
  • @snus74 As you already said: device A (client) <--> PI server, PI client <----> device B (server) - This is the exact setup – V.Hunon Aug 31 '20 at 07:02
  • OK, my understanding from your question is that you can never connect to device A no matter what? – snus74 Aug 31 '20 at 07:03
  • @snus74 That is not exactly right. I can connect to device A alone and I can connect to device B alone. But I can not connect to both of them at the same time. So first if I establish a connection to device B (this works) and then device A, device A will never be connected. If I try to connect with device A while device B is plugged with ethernet, it doesnt even connect to device A and hence, also not connect to B. – V.Hunon Aug 31 '20 at 07:05
  • do you assign different ports to your server and client sockets on the PI? – snus74 Aug 31 '20 at 07:09
  • 1. Hello I tried different ports out of desperation for example: Server 5560 and as Client 5555 but it seems like that it still doesnt work. 2. Out of curiousity, is there a difference in Server and Client ports? – V.Hunon Aug 31 '20 at 07:33
  • There is no difference between "server and client ports". You just can't configure 2 sockets on the same exact IP address and port, each socket should have a unique IP adddress and port, i.e. a unique endpoint. Otherwise how can a remote device know if it connects to a client or a server? – snus74 Aug 31 '20 at 07:42
  • You have to make sure that your remote device B listens to 5555 and device A connects to 5560. Also make sure the servers are started before the clients. In your case startup device B first, then your PI, then device A – snus74 Aug 31 '20 at 07:44
  • @snus74 This is what I did. However, I was not able to establish a connection. Is there some kind of blocking sockets which doesn't allow the raspi to establish a connection while plugged in an ethernet cable? – V.Hunon Aug 31 '20 at 07:55
  • No normally if ports are different and if your app is multithreaded you should be able to have multiple connections. You are using 2 ethernet cables right? – snus74 Aug 31 '20 at 08:05
  • I use 2 Ethernet cables, one is the on-board ethernet interface for device B and the other one is the USB/ethernet dongle which is used for device A. – V.Hunon Aug 31 '20 at 08:06
  • One more possible cause of problem is which IP address you assign to each of your sockets. Can you post a screenshot of ipconfig command and the addresses you assign to both your client and server sockets? Only the IP addresses of the ethernet connections to the PI are needed, when both A and B are plugged in – snus74 Aug 31 '20 at 08:18
  • My raspberry IP is 169.254.244.192 on Port 5555 (Of course I tested on Port 5560 as well) for device A and device B has 169.254.33.63 on Port 5555. On both tests, there was no error message or any incoming connection. – V.Hunon Aug 31 '20 at 08:22
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/220723/discussion-between-snus74-and-v-hunon). – snus74 Aug 31 '20 at 08:53

0 Answers0