Python Socket not on local network - python-3.x

I wrote a basic server-client scripts using sockets, and everything works fine on my LAN, but it doesnt work when im trying to connect to the client thats not in my LAN. I also port forwarded these ports
this is server
###SERVER####
def ChatConnection():
print('Waiting for a connection...\n')
SOCKET = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
SOCKET.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
HOST = ''
PORT = 8989
SOCKET.bind((HOST, PORT))
SOCKET.listen(1)
CONN, ADDR = SOCKET.accept()
print('You can now chat')
while True:
MSG = str(input('\n[YOU]> '))
while not MSG: MSG = str(input('\n[YOU]> '))
CONN.send(MSG.encode())
print('\nAwaiting reply...')
REPLY = CONN.recv(4096).decode()
CONN.close()
this is client
###CLIENT###
def ChatConnection():
print('Waiting for a connection...\n')
while True:
try:
HOST = SERVER EXTERNAL IP
PORT = 8989
SOCKET = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
SOCKET.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
SOCKET.connect((HOST, PORT))
print('You can now chat with server')
print('\nWaiting for server...')
while True:
REPLY = SOCKET.recv(4096)
print('\n[USER]> %s'%REPLY.decode())
MSG = str(input('\n[YOU]> '))
while not MSG: MSG = str(input('\n[YOU]> '))
SOCKET.send(MSG.encode())
print('\nAwaiting reply...')
SOCKET.close()
except Exception: pass
what i need to do so this will work on the WAN?

Make sure that port forward WORKS, to check this run your program and try running a port scan on your public IP.Port scanning tool
Try to change the HOST to 0.0.0.0.
If that didn't work go to CMD and write netstat -a while your script is running.
Search for the port you are listening on and make sure the IP is 0.0.0.0.
If the IP is 0.0.0.0 then try to turn off your Firewall.

Related

Send using UDP between 2 local computers without knowing IP addresses using Python3

I'm trying to develop an app to send a json string from one computer on the wireless network to another (or a phone). The problem is it has to work without knowing the IP address of the recieving computer.
The below code works if i know the IP address to send to
# UDP Server
import socket
IP = "123.123.123.123" # Not actual IP address
PORT = 66666
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((IP,PORT))
while True:
data, addr = sock.recvfrom(1024)
print(f"recieved message: {data} from: {addr}")
# UDP Client
import socket
IP = "123.123.123.123" # Not actual IP address
PORT = 66666
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
MSG = b"Hello there"
sock.sendto(MSG, (IP, PORT))
I can also use sock.getsockname()[0] to get the current IP address and listen to it, but what about sending?
I've read a few tutorials and some say to use 0.0.0.0 to send or listen to all addresses however nothing is recieved with this. The other idea was to use 192.0.0.1 on both ends to listen and send to the router but then I get 'OSError: [WinError 10049] The requested address is not valid in its context'
I thought about using broadcast but have read that this is very bad practice to the point where it was used from ipv6.
I read a suggestion to use multicasting but is there a way to get all IP addresses of computers on the local network in order to use this?
Any assistance would be hugely appreciated!
Thanks to help from rdas referring me to https://gist.github.com/ninedraft/7c47282f8b53ac015c1e326fffb664b5 i've managed to solve the issue with the below;
# UDP Server
import socket
PORT = 66666
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROT_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
sock.bind(("",PORT))
while True:
data, addr = sock.recvfrom(1024)
print(f"recieved message: {data} from: {addr}")
# UDP Client
import socket
PORT = 66666
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROT_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
MSG = b"Hello there"
sock.sendto(MSG, ('<broadcast>', PORT))

How to initiate a socket connection from server to client?

I have setup a tcp socket between a client and a server, very basic. Client side:
#!/usr/bin/env python3
import socket
# create a socket object
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# get local machine name
host = "81.88.95.250"
port = 25000
# connection to hostname on the port.
s.connect((host, port))
# Receive no more than 1024 bytes
msg = s.recv(1024)
s.close()
print (msg.decode('ascii'))
server side:
#!/usr/bin/env python3
import socket
# create a socket object
serversocket = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
# get local machine name
host = socket.gethostname()
port = 25000
# bind to the port
serversocket.bind((host, port))
# queue up to 5 requests
serversocket.listen(5)
while True:
# establish a connection
clientsocket,addr = serversocket.accept()
print("Got a connection from %s" % str(addr))
msg = 'Thank you for connecting'+ "\r\n"
clientsocket.send(msg.encode('ascii'))
clientsocket.close()
My target is to send notification from client to server, and that's easy. The difficult part is that I also need in some circumstances to start the connection from the server and to send a command to the client and this must be executed as soon as it is received, so I cannot setup a periodic "poll". But I'm quite confused on this part, because the client is behind a NAT, not exposed with a public IP.

Searching for Socket hosts and displaying their IP Addresses Python

I'm creating a local client-server game on Python using sockets where a server is hosted on the local network and the clients on the network can connect to the server if they have the server's IP address. It's not a dedicated server so it just runs on another thread on a client's computer. Currently, the client has to manually enter the IP address of the server to connect to it. I want the client to be able to search the network for avaialble servers join, but i'm not sure how to get the server to broadcast it's availability.
This is the server-side script:
totalConnections = 0
port = 5555
host=socket.gethostname()
IP = socket.gethostbyname(host) #this just fetches the computer's IP address so the server can use it
server = IP
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.bind((server, port))
except socket.error as e:
str(e)
s.listen(2)
print("Waiting for a connection, Server Started")
while True:
conn, addr = s.accept()
print("Connected to:", addr)
totalConnections += 1
start_new_thread(threaded_client, (conn, currentPlayer))
currentPlayer += 1
def threaded_client(conn, player):
conn.send(pickle.dumps(all_data[player])) # sends player data to client
While True:
conn.sendall(pickle.dumps(reply))
This is the client-side:
class Network:
def __init__(self,ip):
self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server = ip
self.port = 5555
self.addr = (self.server, self.port)
self.p = self.connect()
def getP(self):
return self.p
def connect(self):
try:
self.client.connect(self.addr)
return pickle.loads(self.client.recv(2048*3))
except:
pass
def send(self, data):
try:
self.client.send(pickle.dumps(data))
return pickle.loads(self.client.recv(2048*3))
except socket.error as e:
print(e)
I found the solution using multicasting on a specific UDP port where all the clients connect to so the data can be shared amongst them : https://pymotw.com/2/socket/multicast.html

How to forward port for server socket using python codes?

I'm very new to socket programming and just tried to write a simple server/client script. When I tried to communicate with them in my own device, it worked. But when I gave my script to my friend so we would communicate remotely, it didn't work (I didnt use 'localhost' as hostname).
Then he forwarded a port using HTTP interface of his router and tried to connect it with a website that tests if a port is forwarded, it was positive (my script didn't connect but this is not our topic).
So I realized I have to forward the port that my server is going to use as well! But the router that I'm using doesn't belong to me, so I can't reach the HTTP interface. In this case my program has to forward a port. But I don't know how to do it and I could not find an example or one that is at my level.
I think this is possible, because apps we use do it every time. I just need some help to figure it out. Thanks...
My little script:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('1. Server')
print('2. Client')
r = int(input("I'm going to be... "))
if r == 1:
host = socket.gethostname()
port = int(input('My port will be... (0 for auto) '))
s.bind((host, port))
sockName = s.getsockname()
print("\nYour Hostname: %s \nYour Port: %d" % (sockName[0], sockName[1]))
#s.listen(int(input('Listen for ... clients')))
input('Enter to listen...')
print('Listening...')
s.listen(1)
for i in range(1):
client, address = s.accept()
print("{}:{} connected!".format(address[0], address[1]))
message = input('Your message (/c to close): ')
if message == '/c':
client.send(message)
print('You sent: ', message.encode('UTF-8'))
else:
client.close()
s.close()
break;
elif r == 2:
host = input('The Hostname of Server is... ')
port = int(input('The Port of Server is... '))
print("\nServer's Hostname: %s \nServer's Port: %d" % (host, port))
input('Enter to connect...')
s.connect((host, port))
print('Connected!')
message = s.recv(4096)
print('Server: ', message.decode('UTF-8'))

Can't set timeout for python 3 recv

I am trying to get a time out on the code below. But it just hangs at the recv and never times out. Can someone point to what I am doing wrong? I have looked and I can't seem to find too much on it.
import socket
host = "localhost"
port = 8888
# create socket object
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# give object the ip and port to listen on
server_address = (host, port)
print('starting up on %s port %s' % server_address)
sock.bind(server_address)
# how many listeners
sock.listen(0)
# sets the time out
sock.settimeout(10)
while True:
print('waiting for a connection')
try:
#this waits for a connection from the sending side.
connection, client_address = sock.accept()
print('connection from', client_address)
start = False
message = ""
while client_address != "":
#this listens and waits for data to be sent and sets it to the data variable
data = connection.recv(32000).decode()
You have set an accept timeout on the listening socket, not a read timeout on the receiving socket.

Resources