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
Related
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.
I have a simple server-client combo running on 2 computers in 2 different networks. The server (a Raspberry) has a TCP tunnel running.
Now running on the code on localhost is fine, on 2 different machines with correct IP and port (I can ping the server via telnet and establish connection via ssh using the same IP and port), I just get the following on the client side AND NOTHING ELSE:
Received SSH-2.0-OpenSSH_7.9p1 Raspbian-10+deb10u2
I should instead receive: Received b'Hello, world'
On the serverside I receive no message at all.
What do I need to run it in 2 different networks? Below the source codes.
server.py:
#!/usr/bin/env python3
import socket
HOST = '' # Standard loopback interface address (localhost)
PORT = 65432 # Port to listen on (non-privileged ports are > 1023)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
with conn:
print("Connected by", addr)
while True:
data = conn.recv(1024)
if not data:
break
conn.sendall(data)
client.py:
#!/usr/bin/env python3
import socket
HOST = 'xxx.xxx.xxx.xxx' # The server's hostname or GLOBAL IP address
PORT = 12345 # The port used by the server, not actually 12345
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
s.sendall(b"Hello, world")
data = s.recv(1024)
print("Received", repr(data))
I tried the basic programs for client and server from realpython (https://realpython.com/python-sockets/#echo-client-and-server)
While these work fine when running on the same computer, there is following problem when trying on different machines:
ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it
Client code:
HOST = '10.0.0.55' # The server's hostname or IP address
PORT = 65432 # The port used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
s.sendall(b'Hello, world')
data = s.recv(1024)
print('Received', repr(data))
Server Code:
import socket
HOST = '127.0.0.1' # Standard loopback interface address (localhost)
PORT = 65432 # Port to listen on (non-privileged ports are > 1023)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
with conn:
print('Connected by', addr)
while True:
data = conn.recv(1024)
if not data:
break
conn.sendall(data)
I can make pings from one computer to the other.
Firewall is turned down
Wireshark shows that the SYN message arrives on the second computer which is answered by a RST message (Wireshark PC server)
If you want the server to be open to other computers, you can't listen on 127.0.0.1 which is basically an inner local loop only located on the computer running the program (that's why it's called loopback in comments). You should have the server listen on its own real address (for example: 10.0.0.55 explicitly).
This however can be annoying if your host can change addresses, an easy workaround is to just use the local IP address like this (on the server):
HOST = socket.gethostbyname(socket.gethostname())
Or if you specifically want to use the address from one network interface:
HOST = '10.0.0.55'
Or, if you want to listen on all network interfaces:
HOST = '0.0.0.0'
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.
I have got a server.py and a client.py.
If i run them on the same computer using the same port and host as 127.0.0.1 it works fine.
I got another laptop connected to the same network. I got my local ip address 129.94.209.9 and used that for the server. On the other laptop I tried connecting to the server but I couldn't.
Is this an issue with my code, with the network or I'm just using the wrong ip address?
Server.py
HOST = '129.94.209.9'
PORT = 9999
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((HOST, PORT))
server_socket.listen(10)
sockfd, addr = server_socket.accept()
send and receive messages etc....
Client.py
HOST = '129.94.209.9'
PORT = 9999
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((HOST, PORT))
except:
print("Cannot connect to the server")
send and receive messages etc...
Client prints "Cannot connect to the server"
Thanks!!
UPDATES: thanks for the comments
1) I did do sockfd, addr = server_socket.accept() sorry I forgot to add it, it was a few lines further down in the code.
2) The error is: [Errno 11] Resource temporarily unavailable
3) Ping does work
EDIT: It is working now when I plug both computers in by ethernet cable to the same network. Not sure why my the won't work when they are right next to each other connected to wifi.
Thanks for all the suggestions! I'll investigate the network issue myself
Using the following code (my IP address rather than yours, of course) I see the expected behaviour.
so8srv.py:
import socket
HOST = '192.168.33.64'
PORT = 9999
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((HOST, PORT))
server_socket.listen(10)
print("Listening")
s = server_socket.accept()
print("Connected")
so8cli.py:
import socket
HOST = '192.168.33.64'
PORT = 9999
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((HOST, PORT))
except Exception as e:
print("Cannot connect to the server:", e)
print("Connected")
When I run it, the server prints "Listening". When I then run the client, both it and the server print "Connected".
You will notice that, unlike your code, my client doesn't just print hte same diagnostic for any exception that's raised, but instead reports the exception. As a matter of sound practice you should avoid bare except clauses, since your program will then take the same action whether the exception is caused by a programming error or a user action such as KeyboardInterrupt.
Also try using this construction to obtain the IP address:
HOST=socket.gethostbyname(socket.gethostname())