I'm trying to read UDP Broadcast messages sent by an device in my network on port 2009. I can see Python receives data from the device, but it's in Bytes. I have tried to decode it with .decode() or .hex(), also with ignore errors, but it's still not "readable".
All I get from the machine is:
b' \x08\x19\x96VDLG\x03\xac\x11P\x00\x00\x00\x00\x01#0\x00\x0bZ'
The code is (very basic):
import socket
import codecs
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
client.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
client.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
client.bind(("", 2009))
while True:
data, addr = client.recvfrom(8192)
print(data)
Maybe someone with a little bit more experience reading broadcast can shed a light for me, because all I try fails.
It should read something like this:
Thanks!
Related
This is the configuration I am using.
Now I want the nodes to send packets in broadcast, but only to nodes directly connected.
sender.py:
import socket
import time
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
server.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
server.settimeout(0.2)
message = b"mymessage"
while True:
server.sendto(message, ('<broadcast>', 37020))
print("message sent!")
time.sleep(1)
receiver.py:
import socket
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) # UDP
client.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
client.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
client.bind(("", 37020))
while True:
data, addr = client.recvfrom(1024)
print(f"received: {data}, from: {addr}\n")
Let's say this is the configuration:
If I run receiver.py on r1,r2,r3, and I run sender.py on r4, i would expect to receive the messages only on the directly connected machines, since I set TTL=1. Instead I receive the message in ALL machines. The output of the receiving machines is received b"mymessage" from 172.17.0.4 (which is the interface I use to manage the virtual nodes, as seen in the picture. Since I don't want the nodes to use that interface, I tried to replace the <broadcast> parameter in sender.py with a more specific one. I first replaced it with 10.255.255.255, but I couldn't receive anything. 0.0.0.0 is not working either. I have a similar issue using multicast, but that would go out of topic. I am probably doing something very wrong here but i can't figure out what.
The final aim, as partially stated above, is to give each nodes the ability to connect ONLY to the adjacent ones, skipping anything that requires more than 1 hop.
Thank you for your time.
I am currently trying to use Socket to multicast audio in real time to an IP and Port.
import socket
MCAST_GRP = '000.0.0.00'
MCAST_PORT = 00000
MULTICAST_TTL = 2
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, MULTICAST_TTL)
with open('C:\\Users\\User\\Downloads\\dog_bark_x.wav', 'rb') as f:
for l in f:
sock.sendto(sock.sendall(l), (MCAST_GRP, MCAST_PORT))
sock.close()
I am currently testing this by using a WAV file. however when i run the code I receive this error:
[WinError 10057] A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
I can send strings without error using code below, meaning the client is connected and listening so im not sure why i am encountering the error above:
import socket
MCAST_GRP = '000.0.0.00'
MCAST_PORT = 00000
MULTICAST_TTL = 2
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, MULTICAST_TTL)
sock.sendto("Test".encode(), (MCAST_GRP, MCAST_PORT))
sock.sendto(sock.sendall(l), (MCAST_GRP, MCAST_PORT))
The inner sock.sendall(l) is working on the unconnected socket, that's why the error. It is likely that you did not mean to use sendall here at all but simply
sock.sendto(l, (MCAST_GRP, MCAST_PORT))
Note though that you are using UDP here which is an unreliable protocol, i.e. datagrams might be lost, duplicated or reordered during transmit. You thus cannot expect that the data will be read by the recipient exactly as they were sent.
Apart from that it is not a good idea to use for line in file when reading binary data.
I'm trying to create some kind of client monitor, like a terminal, to receive data from a serial device over ethernet. I'm trying to use a socket with python, but the problem comes when I create the connection. I'm supposed to receive only one message from the server, and I get the whole message but split into two packets, like this:
Message expected:
b'-- VOID MESSAGE--'
Message received:
b'-- VOID'
b' MESSAGE--'
I don't know if is this a problem of buffer size, decoding or any other function
import socket
TCP_IP = '192.168.#.#'
TCP_PORT = ###
BUFFER_SIZE = 1024
data1=' '
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
while(1):
data = s.recv(BUFFER_SIZE)
print(data.decode('ASCII'))
s.close()
I've already tried with some codecs options like UTF-8, UTF-16 and ASCII but I still get the same result.
This function helped me to solve the issue.
while(1):
cadena += s.recv(1)
if (((cadena)[i])=='\n'):
print(cadena.decode('ASCII'))
cadena=b''
i=-1
i+=1
As it already was said - that's how sockets works.
Sent data could be splitted to chunks. So if you want to be sure, that you've received whole message that was sent you need to implement some kind of protocol, the part of which will be contain length of your message. For example:
First four bytes (integer) represents length of the message
Other bytes - content of the message
In such case algorithm to send a message will be look like:
Count length of the message
Write to socket integer (4 bytes) with message length
Write to socket content of the message
And reading algorithm:
Read bytes from socket and write read data to accumulator-buffer
Read first four bytes from buffer as integer - it will be message length
Check if buffer length is greater or equal "{message length} + 4"
If it's then read required amount of bytes and that will message that was sent.
Drop first "{message length} + 4" bytes from buffer
Repeat from second point
If it's not enough bytes to read message content repeat from first point.
One solution is to use UDP instead of TCP if you can live with the limitations:
There is a size limit, the data must fit into one packet
UDP is "unreliable".
A TCP connection transfer one single stream of bytes. OTOH UDP transfers individual datagrams (messages). If the sender sends N datagrams, the recipient shall receive the same N datagrams. Maybe out of order, maybe some will get lost, but each datagram is independent of all others.
Regarding the limitations, these are not so simple questions. There is plenty of information on these topics, just search.
The max size depends on factors like IPv4 or IPv6, fragmentation etc. and there is a best case and a worst case. Typically you can assume that one ethernet frame (for all headers + payload) is absolutely without problems.
The "unreliability" does not mean the quality of transfer is terrible. The network should work on "best effort" basis. It means there are no ACKs, timeouts and retransmits. You can live without it or you can add simple ACKs to your protocol.
You can use this example.
Server code: (read from client)
#!/usr/bin/python3
from socket import socket, gethostname
s = socket()
host = gethostname()
port = 3399
s.bind((host, port))
s.listen(5)
while True:
print("Listening for connections...")
connection, addr = s.accept()
try:
buffer = connection.recv(1024)
response = ''
while buffer:
response += buffer.decode('ASCII')
buffer = connection.recv(1024)
print(response)
connection.close()
except KeyboardInterrupt:
if connection:
connection.close()
break
Client code: (send message)
#!/usr/bin/python3
from socket import socket, gethostname
s = socket()
host = gethostname()
port = 3399
s.connect((host, port))
print("Sending text..")
s.sendall(b'-- VOID MESSAGE--')
print("Done sending..")
s.close()
While trying to attempt to go for python based socket, I have 2 questions which I am not able to resolve. Kindly help me. Here is my sample socket code:
import socket
import threading
import chardet
bind_ip = '0.0.0.0'
bind_port = 9999
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((bind_ip, bind_port))
server.listen(1) # max backlog of connections
print (('Listening on {}:{}').format(bind_ip, bind_port))
def handle_client_connection(client_socket):
request = client_socket.recv(4096 )
result = chardet.detect(request)
print(result)
print (request.decode(result['encoding']))
client_socket.send('ACK!'.encode(result['encoding']))
client_socket.close()
while True:
client_sock, address = server.accept()
print (('Accepted connection from {}:{}').format(address[0], address[1]))
client_handler = threading.Thread(
target=handle_client_connection,
args=(client_sock,) # without comma you'd get a... TypeError: handle_client_connection() argument after * must be a sequence, not _socketobject
)
client_handler.start()
The above one is server and the below is client:
import socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1', 9999))
client.send(str('test data').encode("utf-16"))
response = client.recv(4096)
print(response.decode("utf-16"))
Now the questions:
1) What is the meaning of the number in this statement: client.recv(4096)? What is 4096, is it bit or byte of kilobyte for data receiving?
2) Can I receive infinite data stream through the socket? Meaning, as this statement client.recv(4096), whatever is the menaing of 4096, may be byte, then the socket will receive the 4096 bytes of data only. I do not have a control on the size of data received through the socket, hence, can I generalize it to accept any size of data through socket?
Please help me get the answers to above queries. I tried the python documentation for socket but didn't found much. I guess I miss something. Please help me get through it.
According to documentation
"If a message is too long to fit in the supplied buffer, excess bytes may be discarded depending on the type of socket the message is received from."
found here
"https://linux.die.net/man/2/recv"
which was from python 3.6 docs
"he maximum amount of data to be received at once is specified by bufsize. See the Unix manual page recv(2)"
found here
"https://docs.python.org/3.6/library/socket.html"
so it is a bytes object and it may actually truncate the message depending on the protocol. So message integrity is handled by the next layer up. So presumably you would loose part of a UDP packet, and you would get either a retry or an additional packet for TCP if the message was too large to fit in the buffer.
I am using python raw sockets to receive data from my browser when i go to the IP on Firefox.
Here is the code:
s = socket.socket(socket.AF_INET, socket.SOCK_RAW)
s.bind(('127.0.0.1', 80))
while True:
while runFlag:
print('running')
data, addr = s.recvfrom(65565)
#data.decode('UTF-8')
print(data)
Returns:
b'E\x00\x01H\x1e\x08\x00\x00\x80\x11Y\xf0\xc0\xa8\x01\x05\xff\xff\xff\xff\x00D\x
00C\x014\x90\xfe\x01\x01\x06\x00B\x19\x8c\xd4\x00\x00\x80\x00\xc0\xa8\x01\x05'...
shortened version of output
I was wondering if anyone could please explain this output to me as I am not sure what it means.