Python Socket Between Devices

I am currently working on controlling a RPI with a Socket Server and Client but when I do it on my PC using 127.0.0.1 but now it wont work on my home network. I know the IP address of the Devices I’m using but it never sees the other device.

PLZ HELP

Server:


#!/usr/bin/env python

import socket
#from neopixel import *

# Create NeoPixel object with appropriate configuration.
#strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL,
#                          LED_STRIP)
# Intialize the library (must be called once before other functions).
#strip.begin()

# Server Variables
TCP_IP = '0.0.0.0'
print "Host: ", TCP_IP
TCP_PORT = 5800
BUFFER_SIZE = 20  # Normally 1024, but we want fast response
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)

# Neopixel Variables
LED_COUNT = 12  # Number of LED pixels.
LED_PIN = 18  # GPIO pin connected to the pixels (must support PWM!).
LED_FREQ_HZ = 800000  # LED signal frequency in hertz (usually 800khz)
LED_DMA = 5  # DMA channel to use for generating signal (try 5)
LED_BRIGHTNESS = 255  # Set to 0 for darkest and 255 for brightest

#Color Variables
color = ""
Red = "0"
Green = "255"
Blue = "0"

conn, addr = s.accept()
print 'Connection address:', addr
while 1:
    data = conn.recv(BUFFER_SIZE)
    if not data: break
    color = data
    print "Color Received:", data
    conn.send(data)  # echo
conn.close()

print "Color: ", color

#Color Choosing
Red, Green, Blue = color.split(",")
print "Red: ", Red
print "Green: ", Green
print "Blue: ", Blue
#for i in range(0,LED_COUNT):
    #strip.setPixelColor(i, color(Red, Green, Blue))
#strip.show()


Client


#!/usr/bin/env python

import socket
import sys


TCP_IP = '192.168.1.125'
TCP_PORT = 5800
BUFFER_SIZE = 1024
nodata = 0
tryip = 1
good = False

while True:

    if tryip == 255:
        print "Can't Find Server..."
        TCP_IP = raw_input("Enter a Custom IP: ")
        if TCP_IP == "":
            print "No Data Sent. Server Should Default Green."
            break
        print "Trying Ip: ", TCP_IP, "\r"

    if tryip == 256:
        print "Custom IP FAILED. No Data Sent. Server SHOULD Default Green."
        break

    if tryip >= 2 and tryip < 255:
        TCP_IP = '10.17.92.'
        TCP_IP += str(tryip)
        print "Trying Ip: ", TCP_IP, "\r"

    while not good:
        MESSAGE = raw_input("Please enter a color: ")
        if MESSAGE == "":
            MESSAGE = "0,255,0"

        if "," in MESSAGE:
            print "you entered", MESSAGE
            good = True
            break
        else:
            print "Not a Color."

    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind((TCP_IP, 5801))
        s.connect((TCP_IP, TCP_PORT))
        s.send(MESSAGE)
        data = s.recv(BUFFER_SIZE)
        s.close()
    except Exception:
        nodata = 1
        if tryip == 1:
            print "Server not on Localhost. Probably Connected to FMS."
        tryip += 1
    else:
        nodata = 0

    if nodata != 1:
        print "sent data:", data
        break


Here’s what I see:

On the client side, you should not bind() the socket to an IP. You just need to use connect()

You do not want to keep connecting to find the IP of your server. You should give it a static IP address, or you can use the Pi mDNS name raspberrypi.local.

Can you clarify your setup a little? I assume that your server is the Pi because it’s controlling the LEDs, but what is your client device? A computer?

Have you looked at https://docs.python.org/2/howto/sockets.html? This doc will explain basic socket usage.

Thank you for all of your help! You have been the FIRST to respond on all of my recent projects posts.

Removing Bind() worked but how do I know they will connect over the FMS with only certain ports open?

Thanks Again, Collin

Happy to help.

Are you running the python client program on the driver station laptop? If not, then I don’t think you need to worry. If so, checkout R60, which has been pretty consistent for the past few years. That will tell you what ports you can use for what.

I am running it on the Driver Station and I know about R60 but the client picks a random port to respond on. How do I fix that?

Also I know all the IPs it could be but is there a way to know immediately what ip or use s.connect much faster?

You are honestly Awesome.

Yes. You need to find out what your Pi’s local IP address is. Try the command

ip addr show

and look for section eth0 and the line inet. Alternately, you can address the Pi using its mDNS name, which is raspberrypi.local. I’m not sure if this is set up by default.

What is the client responding to? It shouldn’t do anything like choose a random port. Your port selection of 5800 should be fine.

If it’s working now (despite taking a time to connect) you should be fine.

I can figure out the IP no problem if I have direct access to it. But I was wondering if theirs an easy way to find it on the FMS. I know about 10.17.92.X but the X is the part I dont know. I currently have code to look through all of the possible ones and I assume that it will probably be in the lower numbers but currently it takes a long time to look through the IP addresses.

And then for the Port thing the Server is on port 5800 which is listed on R60 but the client will reply on something around 57869 which isnt open on the FMS will this be an issue? When I did s.bind it solved this issue but wont connect but now it will pick random port and connect that way.

Like I said, give your Pi a static IP address, or just replace 10.TE.AM.XX with raspberrypi.local.

That will definitely be an issue. You’re right, putting bind() back in the client will fix it. Here’s my code that I tested this with. Uses python 3, so might be a little different than yours.

Client

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 5800))  # Bind to empty IP so it can use anything
s.connect(("192.168.1.3", 5800))  # 192.168.1.3 is the IP of my server
s.send(b"hello")
s.close()

Server

import socket

serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(('', 5800))  # Again, bind to any address, but this specific port
# become a server socket
serversocket.listen(1)

(client, addr) = serversocket.accept()
print("Recieved connection from {}".format(addr))
while True:
    data = client.recv(1024)
    if len(data) == 0:  # According to the spec, empty recieve means that the socket is closing
        break
    print("recv {}".format(data))
client.close()

According to Wireshark, this code only communicates on port 5800.

Thank you So Much for All of your help everything works great now!