Python socket only accepting local connections - python

Server:
import socket
host = ""
port = 4242
backlog = 5
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(backlog)
client, address = s.accept()
while 1:
data = client.recv(size)
if data:
client.send(data)
print(data.decode("utf-8"))
Client:
import socket
import sys
host = sys.argv[1]
port = 4242
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
while True:
line = input("What to say: ")
s.send(line.encode("utf-8"))
Well, I'm a bit confused here. I'm beginning to learn about sockets, so I started out on a simple echo server. The code I've posted above works beautifully when the server is running on Arch Linux or Ubuntu. When it's on Windows 7 however, it only accepts local connections. The thing is, I'm not running a firewall. I'm not sure if Python has a separate WinSock implementation or what, but I'm confused! Please, if you would, I'm quite aware that this is terribly designed (only accepts on client!), but I just want to know why Windows won't accept remote connections.
If it helps, on Arch and Ubuntu, I'm running on Python 3.1, while on Win 7 it's on 3.2.

Sounds like host='' is defaulting to bind to localhost (127.0.0.1) under Win 7 (I don't have access to a Win 7 machine at the moment).
To make your server reachable on all (IPv4) interfaces on the host, this should work on Linux, Windows, Mac, etc:
host = '0.0.0.0'
s.bind((host, 8080))
To verify which address the socket is binding to you can do this:
>>> s.getsockname()
('0.0.0.0', 8080)

As the documentation for Socket states:
Some behavior may be platform dependent, since calls are made to the operating system socket
APIs.
I'm not familiar with Win32 network programming, but I would hazard a guess that it's probably a implementation specific behavior that is triggered when you create a socket without binding it to an address.
My suggestion is move up an abstraction level and use SocketServer.

Related

Windows host can't receive UDP packets from WSL-2 guest

I'm trying to have a simple UDP echo client/server communicate with each other. The client program (which runs in the host Windows) sends packets to the server (which runs in WSL-2), and the server receives them, but the server's reply is never reaches the client.
import sys
from socket import *
from select import select
client = sys.argv[1].startswith("c")
host = sys.argv[2] if len(sys.argv) > 2 else "127.0.0.1"
port = 8080
sd = socket(AF_INET, SOCK_DGRAM)
def poll():
readable, writable, errorset = select([sd], [sd], [sd], 0)
return sd in readable
if client:
sd.connect((host, port))
sd.setblocking(0)
sd.send(b"Hello!")
while not poll():
pass
data, addr = sd.recvfrom(65535)
print(f"RECV {addr} => {data}")
else:
sd.bind((host, port))
print(f"Listening on {host}:{port}")
sd.setblocking(0)
sd.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
while True:
while poll():
data, addr = sd.recvfrom(65535)
print(f"RECV {addr} => {data}")
sd.sendto(data.decode("utf-8").upper().encode("utf-8"), addr)
The output on Windows:
udpecho.py client 172.25.154.133
The output on Linux:
$ python3 udpecho.py server 172.25.154.133
Listening on 172.25.154.133:8080
RECV ('172.25.144.1', 57661) => b'Hello!'
And now I'm stumped. TCP connections work ok so it must only be a UDP thing, but I don't know what to try next.
Running Windows 10 Home edition and hosting Ubuntu-20.04 in WSL 2.
This sounds like this Github issue, where UDP packets smaller than 12 bytes don't make it from WSL2 to the host Windows interface.
If so, then a reported workaround is to turn off transmission checksumming in WSL2 via:
ethtool -K eth0 tx off
It sounds like this may be a Hyper-V networking issue that can be reproduced outside of WSL2, and the Microsoft team says it is under investigation.

How can i connect two computers with python socket?

im new here!
I have a problem with connection between two computers connected with different wi-fi's. After about 20 seconds i get information that connection can't be done.
There is my code:
SERVER:
from socket import *
lista = ['computer']
s = socket(AF_INET, SOCK_STREAM)
port = 21312
s.bind(('my ipv4', port))
s.listen(5)
while True:
for i in range (0, len(lista)):
a = str(lista[i]).encode()
c, addr = s.accept()
print("CONNECTION WITH",addr)
c.send(a)
print(a)
c.close()
CLIENT:
import socket
from socket import *
port = 21312
while True:
s = socket(AF_INET,SOCK_STREAM)
s.connect(('my ipv4', port))
odebrana = (s.recv(1024))
decoded = odebrana.decode()
print(decoded)
s.close()
Likely you are experiencing an issue because your server sits behind a Network Address Translator (NAT). This way your client cannot use the server's IP directly since it is not reachable. There are a few ways around it.
The easiest and not very practical one is: get both machines in the same network, then it should work.
Get a public IP address for the server. You can do that by hosting it on a cloud server that provides you with a public IP, e.g., aws, azure, google cloud etc.
In the old days we used hamachi to get a VPN that would connect both machines. Then they can identify each other over that VPN. Simply turn on hamachi (or any other VPN solution), run your server, then from your client (connected to the VPN), use the VPN's server IP (hamachi will provide you with one when you setup a network).
Disclaimer: I have not used hamachi in about 15 years, but just went through the process because of one of the comments below.
Seems like you can create an account, then once you turn it on you should see your v4 and v6 addresses as shown below:
Highlighted is my v4 address. I suspect you need to create a network, join both PCs in the same network and then use hamachi's IP to emulate behaviour as if they were connected via LAN.
So I faced the similar problem while sending image files between 2 computers using python sockets. I solved the issue by following this way:
First I completed writing the connection code of both server.py and client.py
Note: server.py should be in one computer and client.py should be in another computer.
server.py
import socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
print(host)
server.bind((host, 12000))
server.listen()
client_socket, client_address = server.accept()
file = open('server_image.jpg','wb')
image_chunk = client_socket.recv(2048)
while image_chunk:
file.write(image_chunk)
image_chunk = client_socket.recv(2048)
file.close()
client_socket.close()
client.py
import socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # AF_INET = IP, SOCK_STREAM = TCP
server_host = 'LAPTOP-1231' # Replace this hostname with hostname printed in server.py
client.connect((server_host, 12000)) # 127.0.0.1
file = open('That_Sinking_Feeling_27.jpg', 'rb')
image_data = file.read(2048)
while image_data:
client.send(image_data)
image_data = file.read(2048)
file.close()
client.close()
Now you should add the image in the directory where client.py is located, so that you can send it to another computer (server). Rename it to img.jpg
Then, you need to run server.py in your another computer. It will print the hostname in terminal. Then copy that hostname and paste it in client.py (server_host = hostname_from_server)
Then run client.py
Finally the image will be transferred to new computer (server)

python socket does not connect to other networks

hi guys i'm studying socket in python, i'm having a hard time connecting with other machines
I have this simple code
import socket
host = ''
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((host, 222))
print('wait...')
sock. listen(1)
conn, addr = sock.accept()
print('connected')
the code above is a server, I try to connect using this simple code
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('192.168.0.14', 222))
when I execute the client code, nothing happens, it is in an infinite wait, neither the server responds nor the client responds.
obs: this is my goal to connect to an external network on my network. The server code is running on another network, I want to connect to another network
I ran your code, and it's basically correct. But I don't think your port is perfect, it should be at least 1024.
You should make sure that the port(222) in firewall on your server computer is open.
I changed your port to 12345, it works on my computer.

How to connect my server to other machine using socket library in Python?

I am new to socket library and server side programming. I made 2 scripts which runs perfectly on my machine i.e. server.py and client.py. But when i test it on two different computers it doesn't worked.
What i want is to make my server.py file connected to client.py,
where server.py will run on my machine and it will be connected to
client.py on a separate machine at any location in the world.
I just know socket only. But if this problem can be solved by use of other library, then also it will be fine.
Here is my code:
server.py
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostbyname(socket.gethostname())
port = 12048
s.bind((host, port))
s.listen()
print("Server listening # {}:{}".format(host, port))
while True:
c, addr = s.accept()
print("Got connection from", addr)
c.send(bytes("Thank you", "utf-8"))
client.py
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = '192.168.1.162' # The IP printed by the server must be set here
port = 12048
s.connect((socket.gethostname(), port))
msg = s.recv(1024)
print(msg.decode("utf-8"))
I don't know how it's possible but if it is then please answer this.
Also, i want to receive files from client.py to my machine. Is it possible in socket or i have to import any other library?
Any help will be appreciated.
The reason the client will only connect to the server running on the same computer is because you are using s.connect((socket.gethostname(), port)) instead of s.connect((host, port)). Your host IP variable is never being used. This error means that the client will be trying to connect to its own hostname, which would be itself, and so that is why it only works on one single computer.
You should modify client.py like this:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = '192.168.1.162' # Make sure this is set to the IP of the server
port = 12048
s.connect((host, port))
msg = s.recv(1024)
print(msg.decode("utf-8"))
Now you will be able to connect to a server running on a different computer.
In Client.py you're connecting the socket to socket.gethostname() instead of the ip address of your server. Now, your client is trying to a server that should be running on the same ip as the client. Logically this will work when server and client run on the same ip, but when the client resides on another machine you need to connect to the correct ip address:
s.connect((host, port))
Also, make sure that port is actually open and not blocked by another program. This website helped me open port 7777 on two different laptops and run your edited code on them. You can do the same for port 12048.
Right-click the Start button.
Click Search.
Type Windows Firewall.
Click Windows Firewall.
Click Advanced settings.
Click Inbound Rules in the left frame of the window.
Click New Ruleā€¦ in the right frame of the window.
Click Port.
Click Next.
Click either TCP or UDP.
Click Specific local ports.
Type a port number. (In this case, we will open port 12048.)
Click Next.
Click Allow the connection.
Click Next.
Click any network types you'd like to allow the connection over.
Click Next.
Type a name for the rule.
Click Finish.
I believe for a socket you have to open the TCP port but if that doesn't work you can make a new rule for the UDP port as well.

how can python socket clients have an arbitrary IP while running on one host?

I'm trying to learn something about socket programming in python.
I have written a server which identifies clients first by their IPs , I want to test the program on localhost, but have no idea how to give different IPs to clients. As I know when we use connect() method, we only specify the host and port of the destination, but what if we want to choose ours?! is there any way?
HOST = '127.0.0.1'
PORT = 8018
TIMEOUT = 5
BUF_SIZE = 1024
class WhatsUpClient():
def __init__(self, host=HOST, port=PORT):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((host, port))
logging.info('Connecting to %s:%s' % (host, port))
while 1:
try:
buf = self.sock.recv(BUF_SIZE)
sys.stdout.write(buf)
cmd = raw_input()
if cmd.strip() == '!q':
sys.exit(1)
self.sock.send(cmd)
except:
self.sock.close()
def run(self):
pass
An IP address needs to be unique for the whole world (with a few exceptions), so you can't arbitrarily pick one and use it.
You can look at is private networks (192.168.x.x and 10.x.x.x). The easiest way to set this up is to install a virtual machine (like VirtualBox) on your computer. When you look at the active network interfaces, you'll see that the VM added a few virtual network cards.
If you run your client on the virtual PC, it will get a special, private IP address.
You could also rent a PC in the cloud and run your code there but that costs money.
Another option is to ask your system administrator whether they have any free IP addresses which you can use for testing but usually they don't or they don't want to tell you since it's a bit complicated to set this up.

Categories