I am trying to make a python program which when switched on acts as a client and detects the presence of any servers around it for 15 secs. If it doesn't find any, it promotes itself to a server and broadcasts its own ip as a HOST.
#RECIEVE
s=socket(AF_INET, SOCK_DGRAM)
s.bind(('',37885))
s.settimeout(15)
HOST=s.recvfrom(1024)
s.settimeout(None)
print HOST[0]
#BROADCAST
if (len(HOST)==0):
HOST = gethostbyname(gethostname())
print (HOST)
for i in range(10):
s=socket(AF_INET, SOCK_DGRAM)
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
s.sendto(str(HOST),('255.255.255.255',37885))
time.delay(1)
The problem I am facing is that the program quits as soon as it doesn't find any servers. I need to have a switchable server and client configuration. How can I rectify this problem?
Related
I have been experimenting with the socket library for python. I made a simple program for the server and client where the client can message the server.
Here is my code for the server:
import socket
print("Host")
socket_main = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_main.bind(('127.0.0.1', 9999))
socket_main.listen(1)
conn, addr = socket_main.accept()
while True:
data = conn.recv(1204).decode()
print(data)
conn.close()
Here is my code for the client
import socket
print("Client")
socket_main = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_main.connect(('127.0.0.1', 9999))
while True:
message = input(": ")
socket_main.send(message.encode())
socket_main.close()
When I run these programs in two different terminals on one computer it works just fine, but when I try to run the server and client on different computers I get an error on the clients end saying, "No connection could be made because the target machine actively refused it".
I have tried changing the port multiple times but it didn't help. I have looked through a lot of other forums and I haven't been able to fix this problem for a while now so I decided to ask here.
when I try to run the server and client on different computers I get an error on the clients end
That is because you are using127.0.0.1 on both sides. That is the localhost loopback IP address. It works when the client and server are on the same machine, but it is not routable on the LAN network.
You need to:
change the server to listen on either 0.0.0.0 (to listen on all installed network interfaces), or its actual LAN IP address (just the network interface attached to the LAN).
change the client to connect to the server's hostname or IP address on the LAN.
I have tried changing the port multiple times but it didn't help
The problem is nit with the port, but with the IP address.
I am trying to make a simple app in Python with sockets, but clients only receive the message "Test" sent from the server if they're in the LAN. I tried to run the client (the server is running on my PC) from my laptop and from my PC. In both cases I received the message "Test", but when a friend tries to connect he doesn't receive the message.
Here is my server.py:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 7908))
s.listen(5)
while True:
clientsocket, address = s.accept()
print(f"Connection from {address} established")
clientsocket.send(bytes("Test", "utf-8"))
And here is my client.py:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("my_public_ip_address", 7908))
print(s.recv(8).decode("utf-8"))
I compile client.py with pyinstaller before sending it, so that the script can run without Python being installed on the machine (I don't even have Python on my laptop)
Thanks for taking the time to read and awnsering this :) (Sorry if my english is bad, I'm french)
I guess your friend is outside your LAN: if so you should open/portforward port 7908 on the router to the server.
Open port 7908 on the sever PC firewall.
Your script in this way should work.
I'm using MicroPython with two NodeMCU ESP8266 dev boards. My goal is to connect one to the other, so they can interchange information. One of the boards is running a server program and its AP is up. The other connects to the other board's AP and try to connect.
The server is running fine, and I can connect to it with Kitty using a RAW connection (connecting my PC to the ESP8266 AP). The client, instead, fails in socket.connect() and throws a ECONNABORTED exception. I've used differents settings, but none of them seems to work. How can I connect my two boards? I'm a newbie with sockets, so this may be not a MicroPython specific problem but a Python one.
EDIT: There's no problem when connecting from a PC using the same code. The problem seems to be exclusive of a client ESP8266 connecting to a server ESP8266 through the server Access Point. Maybe a MicroPython bug?
Server code:
import network
import socket
def runServer():
try:
ap_if = network.WLAN(network.AP_IF)
ap_if.active(True)
ap_if.config(essid='MicroPy-AP', password='micropythoN')
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind( ('', 8266) )
s.listen(1)
print("Waiting for a client...")
client, client_ip = s.accept()
print("Connected!")
finally:
print("Closing socket...", end=' ')
s.close()
print("Done.")
Client code:
import network
import socket
def runClient():
try:
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
sta_if.connect('MicroPy-AP', 'micropythoN')
while not sta_if.isconnected():
pass
sta_if.ifconfig()
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
print("Connecting...")
s.connect( ('192.168.4.1', 8266) )
finally:
print("Closing socket...", end=' ')
s.close()
print("Done.")
The stupid answer to this question is that I eventualy switched the programs between the boards, so both of them was running with an 'almost' identical (ESSID and password) Access Point. Although the client was correctly connected to the server AP, I guess that some IP conflict was avoiding the socket to connect.
I have a "server" python script running on one of the local network machines, which waits for clients to connect, and passes them some work to do. The server and client code have both been written, and are working as expected...
The problem is, this server might be running from any machine in the local network, so I can't hard code the address in the script... I immediately wondered if I can make a machine advertise about its existence, and clients can respond to that. Is that doable in Python with the standard library? I really don't have time to download twisted or tornado and learn about them, unfortunately, so I need something simple.
I tried to think more about it, and realized I can have a single static IP machine where servers register/unregister from and clients can look for servers from there. Kind of like a torrent tracker, I think. This'll have to do if I can't do the service advertising approach easily.
An easy way to do service announcement/discovery on the local network is by broadcasting UDP packets.
Constants:
PORT = 50000
MAGIC = "fna349fn" #to make sure we don't confuse or get confused by other programs
Announcement:
from time import sleep
from socket import socket, AF_INET, SOCK_DGRAM, SOL_SOCKET, SO_BROADCAST, gethostbyname, gethostname
s = socket(AF_INET, SOCK_DGRAM) #create UDP socket
s.bind(('', 0))
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1) #this is a broadcast socket
my_ip= gethostbyname(gethostname()) #get our IP. Be careful if you have multiple network interfaces or IPs
while 1:
data = MAGIC+my_ip
s.sendto(data, ('<broadcast>', PORT))
print "sent service announcement"
sleep(5)
Discovery:
from socket import socket, AF_INET, SOCK_DGRAM
s = socket(AF_INET, SOCK_DGRAM) #create UDP socket
s.bind(('', PORT))
while 1:
data, addr = s.recvfrom(1024) #wait for a packet
if data.startswith(MAGIC):
print "got service announcement from", data[len(MAGIC):]
This code was adapted from the demo on python.org
i already have a post which is quite similiar, but i am getting more and more frustrated because it seems nothing is wrong with my network setup. Other software can be seen from the outside (netcat listen servers etc.) but not my scripts.. How can this be??
Note: It works on LAN but not over the internet.
Server:
import socket
host = ''
port = 80001
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(1)
print 'Listening..'
conn, addr = s.accept()
print 'is up and running.'
print addr, 'connected.'
s.close()
print 'shut down.'
Client:
import socket
host = '80.xxx.xxx.xxx'
port = 80001
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
s.close()
Somebody please help me.
Any help is greatly appreciated.
Jake
Edited again to add:
I think you may be missing some basics on socket communication. In order for sockets to work, you need to ensure that the sockets on both your client and server will meet. With your latest revision, your server is now bound to port 63001, but on the local loopback adapter: 127.0.0.1
Computers have multiple network adapters, at least 2: one is the local loopback, which allows you to make network connections to the same machine in a fast, performant manner (for testing, ipc etc), and a network adapter that lets you connect to an actual network. Many computers may have many more adapters (virtual adapters for vlans, wireless vs wired adapters etc), but they will have at least 2.
So in your server application, you need to instruct it to bind the socket to the proper network adapter.
host = ''
port = 63001
bind(host,port)
What this does in python is binds the socket to the loopback adapter (or 127.0.0.1/localhost).
In your client application you have:
host = '80.xxx.xxx.xxx'
port = 63001
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
Now what your client attempts to do is to connect to a socket to port 63001 on 80.xxx.xxx.xxx (which is your wireless internet adapter).
Since your server is listening on your loopback adapter, and your client is trying to connect on your wireless adapter, it's failing, because the two ends don't meet.
So you have two solutions here:
Change the client to connect to localhost by host = 127.0.0.1
Change the server to bind to your internet adapter by changing host = 80.xxx.xxx.xxx
Now the first solution, using localhost, will only work when your server and client are on the same machine. Localhost always points back to itself (hence loopback), no matter what machine you try. So if/when you decide to take your client/server to the internet, you will have to bind to a network adapter that is on the internet.
Edited to add:**
Okay with your latest revision it still won't work because 65535 is the largest post available.
Answer below was to the original revision of the question.
In your code posted, you're listening (bound) on port 63001, but your client application is trying to connect to port 80. Thats why your client can't talk to your server. Your client needs to connect using port 63001 not port 80.
Also, unless you're running an HTTP server (or your python server will handle HTTP requests), you really shouldn't bind to port 80.
In your client code change:
import socket
host = '80.xxx.xxx.xxx'
port = 63001
And in your Server Code:
import socket
host = ''
port = 63001
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostbyname(socket.gethostname()), port ))
In your server script you have port = 80, but you don't ever use it. It looks like the server is listening on 63001. And the client is connecting to 80.
If you're going to use 80, make sure you don't have an http server trying to use the port at the same time as well.