Python Socket communication across networks not working - python

I'm trying to set up communication between me and my friend's computer using the socket module. I run the server code on my computer and he runs the client code on his computer. Here is the code:
Server:
import socket
host = "XXX.XXX.XX.XXX" # IP of my computer
port = 2000
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host, port))
addrs = []
print("Server started")
while True:
data, addr = s.recvfrom(1024)
if not addr in addrs:
addrs.append(addr)
data = data.decode("utf-8")
print("Recieved: " + str(data))
print("Sending: " + data)
for add in addrs:
s.sendto(data.encode("utf-8"), add)
Client:
import socket
import time
host = "XXX.XXX.XXX.XXX" # External IP of my router
port = 2001
server = (host, port)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setblocking(False)
while True:
message = "Test message"
time.sleep(1)
print("Sending: " + message)
s.sendto(message.encode("utf-8"), server)
try:
data, addr = s.recvfrom(1024)
except BlockingIOError:
pass
else:
data = data.decode("utf-8")
print("Recieved: " + str(data))
Note: The port in the client vs. server code is different to make sure that my port forwarding is actually doing something.
I have set up port forwarding on my router. Everything works fine when I run both scripts on my computer (or even another computer connected to the same WiFi as mine) and I know that the port forwarding is doing its thing. However, when my friend (who is connected to a different WiFi) runs the client code, it doesn't work. No error is thrown, but he sends data which neither my computer nor the router's port forwarding rule recieves.
Could this problem originate from my code, or is it more likely to be because of my router not being properly set up?

Okay I setup a HotSpot my Android Phone. which in this case is your "Router", used my phone's IP Address. and On the computer tried to run your client code, its sending test messages on the client:
Sending: Test message
Sending: Test message
Sending: Test message
Sending: Test message
....
but I'm receiving nothing on your Server, still saying server started.
so I configured your host variable on the "Client App" like so, also your ports are not consistent 2000 on server and 2001 on client:
host = "" # External IP of my router
port = 2000
NOTE!! I left the host Empty
Because I think for some reason the server is hosted locally on the pc, you are running the server on. This way i can also Connect locally from the same computer I ran the server app with:
host = "localhost" # External IP of my router
on the your client app.
this is how everything looks.
Server Code
run this on your comuter.
import socket
host = "" # IP of my computer
port = 2000
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host, port))
addrs = []
print("Server started")
while True:
data, addr = s.recvfrom(1024)
if not addr in addrs:
addrs.append(addr)
data = data.decode("utf-8")
print("Recieved: " + str(data))
print("Sending: " + data)
for add in addrs:
s.sendto(data.encode("utf-8"), add)
Depending on where you ran your serverApp. use the IP of the computer running the server. I'm Still learning so I don't know how to set it up to use your router's IP.
ClientApp Code
run this on your friend computer or more. or on android even.
import socket
import time
host = "ip_of_the_computer_the_server_is_running_on" # connecting from another computer
#host = "localhost" # If you connecting locally
port = 2000
server = (host, port)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setblocking(False)
while True:
message = "Test message"
time.sleep(1)
print("Sending: " + message)
s.sendto(message.encode("utf-8"), server)
try:
data, addr = s.recvfrom(1024)
except BlockingIOError:
pass
else:
data = data.decode("utf-8")
print("Recieved: " + str(data))
And use Your router only for same AP Connection.
Tested with my TOTO-LINK IT WORKS FINE. as long as I don't use my router's IP On the client host.
Demonstrations
Server
CLient
Client On Mobile

This code is actually 100% correct, the error was in my port forwarding.

Related

How to send a simple UDP message from my local computer(client.py) to a remote server pythonanywhere(server.py)

I want to send a simple UDP message from my local computer(client.py) to a remote server pythonanywhere(server.py). I don't actually know if I'm doing it right, or maybe what I did is not a good practice. How can I do that? I'm still a beginner in socket programming.
client.py(local computer)
import socket
ip = "<insert ip here>"
port = 9999
Message = "Hello, Server"
clientSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
clientSock.sendto(Message.encode('utf-8'), (ip, port))
server.py(pythonanywhere)
import socket
ip = "<insert ip here>"
port = 9999
serverSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
serverSock.bind((ip, port))
while True:
data, addr = serverSock.recvfrom(4096)
print("Message: ", data)
You cannot run a udp socket server on PythonAnywhere. PythonAnywhere does not route arbitrary network traffic to the machines where you would be running the server code.

What all things do i have to change in my socket programs to make it work for computers on different networks

If i have simple socket program with server and client programs to send a message how do I modify it to make it work for different networks. (say my friend and i want to send hi from our pcs)
The error message is:
TimeoutError: [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
#Server
import socket
host = 'local host'
port = 5000
s = socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
s.bind(('', port))
s.listen(1)
c, addr = s.accept()
print("CONNECTION FROM:", str(addr))
c.send(b"Hi")
msg = "Bye.............."
c.send(msg.encode())
c.close()
#Client
import socket
host = 'local host'
port = 5000
s = socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
s.connect(('127.0.0.1', port))
msg = s.recv(1024)
while msg:
print('Recived:' + msg.decode())
msg = s.recv(1024)
s.close()
Set up port forwarding on your router. Suppose your local system is the server serving on port 5000 and your friend is the client.
Open an Command Prompt on the server and run ipconfig to get your local IP address. It is usually of the form 192.168.x.x but can vary. It should also be available in your router's status page.
On your router, configure port forwarding for internal IP = local IP, interal port = 5000, external port = 5000.
Your router should also have your external Internet address on its status page. You can also just google whatsmyip. Give that IP and the external port number (5000) to your friend. They use that to connect their client to your server.

Connect multiple computers with sockets (python)

I am trying to connect multiple computers with sockets. I can run host and client on my computer, and they will connect. But if i try to run client on another computer, it wont connect. This is my host code:
import socket
import requests
# NOTES:socket.gethostname()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('0.0.0.0', 1234))
s.listen(5)
print("Searching for available computers...")
while True:
clientsocket, address = s.accept()
print(f"Connection from {address} has been established!")
usr = input("Temporary username for this session: ")
msg = input("Send to client: ")
clientsocket.send(bytes(usr + " says > " + msg, "utf-8"))
break
while True:
msg1 = input("Send to client: ")
clientsocket.send(bytes(usr + " says > " +msg1, "utf-8"))
#w
and this is my code for client:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), 1234))
while True:
msg = s.recv(1028)
print(msg.decode("utf-8"))
what is wrong?
That is because the IP address the server is listening on, is 0.0.0.0 (localhost) only programs on the same computer can access that IP address. Change the IP address from the server to socket.gethostbyname(socket.gethostname()) that will return the local IP address of your computer. And that local IP address can be accessed by anyone, who is connected to the same network. In the code of the client, you have to change the IP address to the IP address, returned from the function above. So run print(socket.gethostbyname(socket.gethostname()))on the server computer and set the IP address the client is connecting to, to the printed value.
The "0.0.0.0" part is correct (keep in mind that this config allows any ip address to connect to the server (from WAN and from LAN)).
You have to change this:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), 1234))
while True:
msg = s.recv(1028)
print(msg.decode("utf-8"))
into this:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("ip of the server", 1234))
while True:
msg = s.recv(1028)
print(msg.decode("utf-8"))
Because the socket.gethostname() command is meant to get the ip address of the machine you are running the program on (not the server itself... infact if not specified there is no way the client can know on what address the server is located)
p.s.
remember to open port 1234 on the server machine
+
please don't use 1028... that's a very bad number: use 1024 instead

Python Socket, how do i choose between s.send and conn.send?

def send_Button():
try:
myMsg = "ME: " + text.get()
msg = text.get()
conn.send(msg) ###
textBox.insert(END, myMsg + "\n")
textEntry.delete(0, END)
textBox.yview_pickplace("end")
except NameError:
myMsg = "ME: " + text.get()
msg = text.get()
conn.send(msg) ###
textBox.insert(END, myMsg + "\n")
textEntry.delete(0, END)
textBox.yview_pickplace("end")
This program uses the tkinter module with socket in python2.7. My program allows for you to either connect to a server to chat with or host a server for others to connect to you, but whenever I try and test it out then the lines with the '###' on always bring up an error and it doesn't work, the error which comes up is: "NameError: global name 'conn' is not defined" OR "error: [Errno 10057] A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied".
Any help please?
I think that you are trying to get the program to act as a Client or as a Server just changing s.send() to conn.send() saddly it isn't that simple.
Socket Initializzation
The socket have to be initialized before sending or receiving data.
For a client usually it's something like this.
send_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # Create the socket
send_socket.connect((serverIp, serverPort)) # Connect to the server
send_socket.send(data) # Send the data to the server
And like this for a Server:
listen_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # Create the socket
listen_socket.bind(("0.0.0.0", port)) # Set the socket to accept client from every interface on the port port
listen_socket.listen(1) # Put the server on listen on the port setted before
accept_socket, addr = self.listen_socket.accept() # when a client connect return the socket to talk with it
data = self.accept_socket.recv(buffer_size) # Receive data form the client of max size buffer_size
Docs examples
From your question I guess that with s.send() and conn.send() you are talking about
this example from the python 2.7 socket docs
Here are four minimal example programs using the TCP/IP protocol: a server that echoes all data that it receives back (servicing only one client), and a client using it. Note that a server must perform the sequence socket(), bind(), listen(), accept() (possibly repeating the accept() to service more than one client), while a client only needs the sequence socket(), connect(). Also note that the server does not sendall()/recv() on the socket it is listening on but on the new socket returned by accept().
Client
Echo client program
import socket
HOST = 'daring.cwi.nl' # The remote host
PORT = 50007 # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall('Hello, world')
data = s.recv(1024)
s.close()
print 'Received', repr(data)
the client is pretty stright forward, it create the socket s and then after using s.connect() it just send data through it.
Server
The server one is where there there are both s and conn
Echo server program
import socket
HOST = '' # Symbolic name meaning all available interfaces
PORT = 50007 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr
while 1:
data = conn.recv(1024)
if not data:
break
conn.sendall(data)
conn.close()
in this one first of all we create a socket s on which the server will listen and then using s.accept() it will wait till a client connect to the server and then return the conn which is the socket of the connected client.
So to receive or send data to the client you have to use conn.
Notes
As said in the documentation in these two example the server accept only one client. So if you want to deal with multiple clients you have to repeat the accept step and possibly generate a new Thread for each client so that other clients don't have to wait for each others.

TCP Python Socket Server Response

I'm writing a TCP python script that will act as a server and retrieve a temperature reading from a machine (the client). I need to pass a command to the client from the server and listen for an output of the response. I successfully reach the cmd definition line, but when s.accept() is called I'm left hanging with no response from the client.
Server.py
import socket
port = 7777
ip = raw_input('192.168.62.233')
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((ip, port))
s.listen(1)
print "waiting on port: ", port
while True:
cmd = raw_input('KRDG? A[term]')#command send to client
conn, addr = s.accept()
s.send(cmd)
print "It sent"
data = conn.recv(4096)
print "Received:", data, " from address ", addr
Edit:
I believe you're correct, I should consider my code the client and temperature readout at the server. I do now get left hanging after "here 2" when I go to s.recv().
Client.py
import socket
ip = '192.168.62.233'
port = 7777 # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, port))
print 'here'
s.send('KRDG? A[term]')
print 'here 2'
data = s.recv(4096)
print 'here 3'
s.close()
print 'Received', repr(data)
Usually, a TCP server accept will block while it waits for a client to connect. Have you checked to make sure that you client can and is connecting? You could use a tool like tcpdump or similar to watch the network activity and make sure the client is connecting.

Categories