I have been trying to send broadcast message for a long time but unable to receive it at all from the other side and no error at all. Server side it quickly sends packet and client keeps listening but never prints. Please answer me if someone really did this. I am using two virtual machines of same linux ubuntu. One for server and other for client.
#client
from socket import *
s = socket(AF_INET, SOCK_DGRAM)
s.bind(("192.168.1.255",12345))
print s.recvfrom(4096)[0]
#server
from socket import *
s = socket(AF_INET, SOCK_DGRAM)
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
s.sendto("hi i am server!", ("<broadcast>", 12345))
I solved it myself.
Server side:
from socket import *
s = socket(AF_INET, SOCK_DGRAM)
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
s.sendto("hi i am server!", ("192.168.1.255", 12345))
Client side:
from socket import *
s = socket(AF_INET, SOCK_DGRAM)
s.bind(("192.168.1.255",12345))
print s.recvfrom(4096)[0]
Instead of using "<broadcast>" as an address we should use the same subnet address
Related
As part of a uni course, I have to write a simple python TCP client-server chat but I'm having issues getting the sockets in the server.py and client.py programs to connect.
After many attempts I decided to really strip back the program to just try to connect the sockets and have the client send one message to the server after they are connected.
I am running the two programs (server.py and client.py) on the same computer (macOS) in separate terminal windows. I have tried turning off the firewall and running the programs as well just in case that was somehow causing an issue.
My code is as below:
server.py - This is run first
from socket import *
serverPort = 11500
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(('', serverPort))
print("The server is listening")
serverSocket.listen(1)
clientSocket, clientAddress = serverSocket.accept()
message, clientAddress = serverSocket.recvfrom(2048)
client.py - Once server.py is running, this is then started
from socket import *
serverName = "127.0.0.1"
serverPort = 11500
clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect((serverName, serverPort))
message = "Hello"
clientSocket.send(message.encode())
This is the error I have been receiving:
(base) me#ME python_socket % python3 tcp_server.py
The server is listening
Traceback (most recent call last):
File "tcp_server.py", line 11, in <module>
message, clientAddress = serverSocket.recvfrom(2048)
OSError: [Errno 57] Socket is not connected
Thanks in advance for any help. It seems like something that should be really simple but even after watching tutorials online I still seem to have the issue of the sockets not connecting.
Problems
You should use recv() instead of recvfrom() when you connect using TCP. recvfrom() is used for UDP socket.
Instead of receiving data from serverSocket, you should use newly created TCP clientSocket.
Correct Solution
Server
from socket import *
serverPort = 11500
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(("localhost", serverPort))
print("The server is listening")
serverSocket.listen(1)
clientSocket, clientAddress = serverSocket.accept()
message = clientSocket.recv(2048).decode()
print(message)
Client
from socket import *
serverName = "127.0.0.1"
serverPort = 11500
clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect((serverName, serverPort))
message = "Hello"
clientSocket.send(message.encode())
Server Output:
The server is listening
Hello
The issue is that, in the server.py code, you should replace serverSocket in the recvfrom line with clientSocket, since when you call accept right before that line, clientSocket (returned by accept) is a new socket specific to that connection.
clientSocket, clientAddress = serverSocket.accept()
message, clientAddress = clientSocket.recvfrom(2048)
After that change, it is going to work just fine.
I'm new to how networking works and I'm trying to write two scripts for a class assignment, one acts as a server and one as a client. Both the server and client scripts are to be run on the same computer and each one uses two different ports (client port and server port). The client should be able to send a message to the server and then get a message back if the send was successful. This is the client code:
from socket import *
serverName = 'hostname'
serverPort = 2000
clientSocket = socket(AF_INET, SOCK_DGRAM)
message = input('Input lowercase sentence:')
clientSocket.sendto(message.encode(), (serverName, serverPort))
modifiedMessage, serverAddress = clientSocket.recvfrom(3000)
print(modifiedMessage.decode())
clientSocket.close()
And this is the server code:
from socket import *
serverPort = 2000
serverSocket = socket(AF_INET, SOCK_DGRAM)
serverSocket.bind(('', serverPort))
print("The server is ready to receive")
while True:
message, clientAddress = serverSocket.recvfrom(3000)
modifiedMessage = message.decode().upper()
serverSocket.sendto(modifiedMessage.encode(), clientAddress)
The server code runs fine but I get this error from running the client code:
socket.gaierror: [Erno 11001] getaddrinfo failed
Specifically, it doesn't like
clientSocket.sendto(message.encode(), (serverName, serverPort)
I saw multiple threads on here about this error but none of them really helped with my issue. I already checked to ensure both the ports are definitely open before executing both scripts, and they are. My initial guess is that it can't find the actual server port, even though it's up and running and waiting for a response. So I'm stumped. What does this error mean and how can I resolve this?
You forgot to actually connect the client socket to the server socket before trying to send a message:
from socket import *
serverName = 'localhost'
serverPort = 2000
clientSocket = socket(AF_INET, SOCK_DGRAM)
clientSocket.connect((serverName, serverPort))
message = input('Input lowercase sentence:')
clientSocket.sendto(message.encode(), (serverName, serverPort))
modifiedMessage, serverAddress = clientSocket.recvfrom(3000)
print(modifiedMessage.decode())
clientSocket.close()
I also changed the serverName to localhost.
Here is broadcast server
from time import sleep
from socket import *
PORT = 50000
s = socket(AF_INET, SOCK_DGRAM)
s.bind(('', 0))
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
data = "I am server"
while 1:
s.sendto(data, ('<broadcast>', PORT))
print "sent data"
sleep(5)
Please note that you need to change '<broadcast>' with actual broadcast address of your network. Please see Python can't send a broadcast package with address
Here is broadcast receiver
from socket import socket, AF_INET, SOCK_DGRAM
PORT = 50000
client = socket(AF_INET, SOCK_DGRAM)
client.bind(('0.0.0.0', PORT))
data, addr = s.recvfrom(1024) #sticks here forever!
if data:
print "Found Broadcast server at : " + addr
But problem is that my receiver just sticks at s.recvfrom(1024)
While through tcpdump I am able to see the packet, then why this python client is not able to catch it ?
command is sudo tcpdump -i wlan0 ip -X dst host 255.255.255.255
I changed your code to Python 3 and corrected 2 errors:
Change s to client
Print the statement only when there is data from recvfrom()
Hope it helps.
from socket import socket, AF_INET, SOCK_DGRAM
PORT = 50000
client = socket(AF_INET, SOCK_DGRAM)
client.bind(('0.0.0.0', PORT))
while True:
data, addr = client.recvfrom(1024) #sticks here forever!
if data:
print("Found Broadcast server at : ", addr)
You need to set socket options before you bind it, and you need to bind it to INADDR_BROADCAST.
How do I get a response from the server?
Client side:
#CLIENT
import socket
import time
host = "localhost"
port = 5454
data_c = input()
c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
c.sendto(bytes(data_c, 'utf-8'),(host,port))
print( data_c )
print( c.recv(1024).decode('utf-8'))
SERVER side:
#SERVER
import socket
import time
host = "localhost"
port = 5454
data_s = "ACKNOWLEDGMENT"
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host, port))
print(s.recv(1024).decode('utf-8'))
I can send a message from the server that the client will receive, but can not seem to get communication (like an ACK.) to make it back to the server.
(yes UDP is not a good way to be doing this i'm pretty sure, but that was a specific for the project)
for question 1: to send the ACK, you could replicate what you have in the reverse direction.
Since UDP is connection-less you don't know beforehand you receive a packet where the packet will come from, so you have to use recvfrom to get both the packet and the peer (address/port) the packet came from. Then you have to use that address to send data back.
What you're doing now in your client (but what really looks like the server) in the loop is send the same data over and over to itself. Instead in the loop you should receive packets using the previously mentions recvfrom then send replies to the peer you received the packet from.
So something like the following pseudo code
while True:
peer = recvfrom(...)
sendto(..., peer)
After many attempts to get a simple acknowledgment reply from my server this did it.
Beyond literally starting completely over each round, the time.sleep(.1) function was the only missing key. It allowed the server and client both time to close the current socket connection so that there was not an error of trying to bind multiple bodies to a single location or something.
OSError: [WinError 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted
Working result:
#SERVER
import socket
import time
host = "localhost"
port = 5454
data_s = "ACKNOWLEDGMENT"
while 1:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host, port))
received = print("Client: " + s.recv(1024).decode('utf-8')) #waiting to receive
s.close
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
time.sleep(.1)
s.sendto(bytes(data_s, 'utf-8'),(host,port)) #sending acknowledgment
print("Server: " + data_s)
s.close # close out so that nothing sketchy happens
time.sleep(.1) # the delay keeps the binding from happening to quickly
Server Command Window:
>>>
Client: hello
Server: ACKNOWLEDGMENT
Client:
#CLIENT
import socket
import time
host = "localhost"
port = 5454
c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while 1:
data_c = input("Client: ")
c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
c.sendto(bytes(data_c, 'utf-8'),(host,port)) #send message
c.close
# time.sleep()
c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
c.bind((host, port))
print("Server: " + c.recv(1024).decode('utf-8')) # waiting for acknowledgment
c.close
c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
time.sleep(.1)
Client Command Window:
>>>
Client: hello
Client: hello
Server: ACKNOWLEDGMENT
I did finally remove the redundant input("Client: ") there at the top.
A special thanks #JoachimPileborg for helping, but I have to give it to the little guy just because it was the path I ended up taking.
I just want to broadcast a udp message on a specific port on my network. How can I accomplish this in python?
This will only work with IPv4 networks:
BC_PORT = 12345
import sys, time
from socket import *
s = socket(AF_INET, SOCK_DGRAM)
s.bind(('', 0))
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
s.sendto("hello world", ('<broadcast>', BC_PORT))