Python UDP-Receive buffer being overwritten - python

I have a client(written in Python) and a server(writted in C)
Here is part of my code for python udp client:
for x in range(noResults):
fName, addr = sock.recvfrom(1000)
print "Name:", fName
resultList[x].name=fName.strip('\x00')
fSize, addr = sock.recvfrom(1000)
print "Size:", fSize
resultList[x].size=fSize.strip('\x00')
fPort, addr = sock.recvfrom(1000)
print "Port:", fPort
resultList[x].port=fPort.strip('\x00')
fIP, addr = sock.recvfrom(1000)
print "IP:", fIP
resultList[x].ip=fIP.strip('\x00')
sys.stdout.flush()
print "IP:",resultList[x].ip
i=i+1
while the output it produces after communicating with server(written in C) is:
Name: travel Prague.mp4
Size: 1936l Prague.mp4
Port: 5008l Prague.mp4
IP: 127.0.0.1gue.mp4
IP: 127.0.0.1gue.mp4
How can i solve this problem?

I finally changed my server to make a new char string for sending each of name,size,ip,port and send that string via UDP and that solved the problem
Thanks ALL!!

Related

How to send data via bluetooth to Pi pico

I need a way to send data to and from my pi pico via bluetooth.
Here is the program I'm running on my pc.
Note: Everything on the pi is working correctly (tested with a bt serial terminal)
import bluetooth as bt
print("Scanning Bluetooth Devices....")
devices = bt.discover_devices(lookup_names=True)
for addr, name in devices:
print("%s : %s" % (name, addr))
dev_name = input("Enter device name: ")
dev = ""
check = False
for addr, name in devices:
if dev_name == name:
dev = addr
check = True
if not check:
print("Device Name Invalid!")
else:
print("Attempting to connect to %s : %s" % (dev_name, dev))
hostMACAddress = dev
port = 3
backlog = 1
size = 1024
s = bt.BluetoothSocket(bt.RFCOMM)
s.bind((hostMACAddress, port))
s.listen(backlog)
try:
client, clientInfo = s.accept()
while 1:
data = client.recv(size)
if data:
print(data)
client.send(data) # Echo back to client
except:
print("Closing socket")
client.close()
s.close()
It doesn't throw any errors but I don't get anything printed to the terminal when the pi should send "R"
Edit: Here is the working code for anyone interested :)
import bluetooth as bt
print("Scanning Bluetooth Devices....")
devices = bt.discover_devices(lookup_names=True)
for addr, name in devices:
print("%s : %s" % (name, addr))
dev_name = input("Enter device name: ")
dev = ""
check = False
for addr, name in devices:
if dev_name == name:
dev = addr
check = True
if not check:
print("Device Name Invalid!")
else:
print("Sending data to %s : %s" % (dev_name, dev))
hostMACAddress = dev
port = 1
backlog = 1
size = 8
s = bt.BluetoothSocket(bt.RFCOMM)
try:
s.connect((hostMACAddress, port))
except:
print("Couldn't Connect!")
s.send("T")
s.send("E")
s.send("S")
s.send("T")
s.send(".")
s.close()
The most straight forward (but not the most efficient way) is to convert the array of integer to a delimited C string and send it the way you are sending "Ready".
Let assume the array delimiters are "[" and "]" then the following array
int arr[] = {1,2,3};
can be converted to a string like the following
char str[] = "[010203]";
To convert array of integer to the delimited string you can do the following:
int arr[] = {1,2,3};
int str_length = 50; // Change the length of str based on your need.
char str[str_length] = {0};
int char_written = 0;
char_written = sprintf(str,'[');
for (int i = 0; i< sizeof(arr)/sizeof(int) - 1; i++){
char_written = sprintf(&str[char_written], "%02d", arr[i]);
char_written = sprintf(&str[char_written], ']');
Now you can use your existing code to send this string. In the receiving end, you need to process the string based on "[", "]", and the fact that each integer has width of 2 in the string.
Edit: Converting array to string and send the string via bluetooth via python.
To convert an array to string in python the following will do the job
a = [1,2,3,4,5]
a_string = "[" + "".join(f"{i:02d}" for i in a) + "]"
To send this string via python over bluetooth you need to use PyBlues library.
First you need to find the MAC address of the pico bluetooth
import bluetooth
# Make sure the only bluetooth device around is the pico.
devices = bluetooth.discover_devices()
print(devices)
Now that you know the MAC address, you need to connect to it
bt_mac = "x:x:x:x:x:x" # Replace with yours.
port = 1
sock=bluetooth.BluetoothSocket(bluetooth.RFCOMM)
sock.connect((bd_addr, port))
Know you can send strings like
sock.send(a_string.encode())
Finally, in the end of your python program close the socket
sock.close()
PS: I do not have bluetooth available to test it but it should work.

python udp listener not showing on process listening to ports

I have a script which listens to incoming udp packets on port 8087:
IP_ADDRESS = '0.0.0.0'
LISTEN_PORT = 8087
serverSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
serverSock.bind((IP_ADDRESS, LISTEN_PORT))
while True:
data, addr = serverSock.recvfrom(1024)
I run the script and can get data if I send packets to it.
When I do sudo netstat -peant | grep ":8087 " to see the process listening on this port, I don't have any results.
When I do sudo netstat -peant | grep ":80 " for example, I do get results of processes listening on this port.
Why is that? something wrong with the udp server code? shouldn't it listen on 8087?
your server listens to the correct port but need proper data handling.
study below code and you will get a good understanding on this.
from socket import *
import string
from time import ctime
HOST = '127.0.0.1'
PORT = 8087
BUFSIZ = 1024
ADDR = (HOST, PORT)
ssock = socket(AF_INET, SOCK_STREAM)
ssock.bind(ADDR)
ssock.listen(5)
try:
while True:
c = 1
print 'Waiting for a connection...'
csock, addr = ssock.accept()
hostname, aliases, addresses = gethostbyaddr(addr[0])
lip, lport = ssock.getsockname()
print '''
Connected ...
Remote Host : %s
Remote host IP : %s
Remort Port : %d
Connected time : %s
Local IP : %s
Local Port : %d \n''' % (hostname , addr[0], addr[1], ctime(), lip, lport)
while True:
data = csock.recv(BUFSIZ)
if data == 'q':
break
elif data == 'shut':
ssock.close()
break
elif data == ' ':
csock.send('Server Responce: <> \n')
print 'srv responces: %d : <>' % c
c += 1
else:
data1 = data.upper()
csock.send('Server Responce: %s \n' % data1)
print 'srv responces: %d : <%s>' % (c, data1)
c += 1
csock.close()
except:
print 'Server socket closed !!!'

Socket Programming; File corrupts when transferring over multiple devices

The problem I'm having is to get a file from the server to client across devices. Everything works fine on localhost.
Lets say I want to "get ./testing.pdf" which sends the pdf from the server to the client. It sends but it is always missing bytes. Is there any problems with how I am sending the data. If so how can I fix it? I left out the code for my other functionalities since they are not used for this function.
sending a txt file with "hello" in it works perfectly
server.py
import socket, os, subprocess # Import socket module
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
#host = ''
port = 5000 # Reserve a port for your service.
bufsize = 4096
s.bind((host, port)) # Bind to the port
s.listen(5) # Now wait for client connection.
while True:
c, addr = s.accept() # Establish connection with client.
print 'Got connection from', addr
while True:
userInput = c.recv(1024)
.... CODE ABOUT OTHER FUNCTIONALITY
elif userInput.split(" ")[0] == "get":
print "inputed get"
somefile = userInput.split(" ")[1]
size = os.stat(somefile).st_size
print size
c.send(str(size))
bytes = open(somefile).read()
c.send(bytes)
print c.recv(1024)
c.close()
client.py
import socket, os # Import socket module
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
#host = '192.168.0.18'
port = 5000 # Reserve a port for your service.
bufsize = 1
s.connect((host, port))
print s.recv(1024)
print "Welcome to the server :)"
while 1 < 2:
userInput = raw_input()
.... CODE ABOUT OTHER FUNCTIONALITY
elif userInput.split(" ")[0] == "get":
print "inputed get"
s.send(userInput)
fName = os.path.basename(userInput.split(" ")[1])
myfile = open(fName, 'w')
size = s.recv(1024)
size = int(size)
data = ""
while True:
data += s.recv(bufsize)
size -= bufsize
if size < 0: break
print 'writing file .... %d' % size
myfile = open('Testing.pdf', 'w')
myfile.write(data)
myfile.close()
s.send('success')
s.close
I can see two problems right away. I don't know if these are the problems you are having, but they are problems. Both of them relate to the fact that TCP is a byte stream, not a packet stream. That is, recv calls do not necessarily match one-for-one with the send calls.
size = s.recv(1024) It is possible that this recv could return only some of the size digits. It is also possible that this recv could return all of the size digits plus some of the data. I'll leave it for you to fix this case.
data += s.recv(bufsize) / size -= bufsize There is no guarantee that that the recv call returns bufsize bytes. It may return a buffer much smaller than bufsize. The fix for this case is simple: datum = s.recv(bufsize) / size -= len(datum) / data += datum.

Cannot Get Strings Across in a Socket Program

I have been looking at some code for a small chat program that I found online. It was originally written for 2.7, but it seems to work with 3.2. The only problem is that I cannot send strings, only numbers:
The chat.py file source code:
from socket import *
HOST = ''
PORT = 8000
s = socket(AF_INET, SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print ('Connected by ' + str(addr))
i = True
while i is True:
data = conn.recv(1024)
print ("Received " + repr(data))
reply = str(input("Reply: "))
conn.send(reply)
conn.close()
And the client.py source file:
from socket import *
HOST = ''
PORT = 8000
s = socket(AF_INET, SOCK_STREAM)
s.connect((HOST, PORT)) # client-side, connects to a host
while True:
message = str(input("Your Message: "))
s.send(message)
print ("Awaiting reply...")
reply = s.recv(1024) # 1024 is max data that can be received
print ("Received " + repr(reply))
s.close()
When I run these using two separate terminals, they work, but do not send strings.
Thank you
When you work with sockets, the message you're passing around should probably be in bytes, b'bytes'. In Python 2.x, a str is actually what a bytes is in Python 3.x
So your message should be something like:
message = b'Message I want to pass'
Check here http://docs.python.org/3.3/library/stdtypes.html for more information.
According to http://docs.python.org/3/library/functions.html#input input returns a str, which means you'll have to encode message into bytes as such:
message = message.encode()
Do verify that this is the right approach to convert str to bytes by checking the type of message.
Your socket code is correct, it was just failing due to an unrelated error due to raw_input vs input. You probably intended to read a string from the shell instead of reading a string and trying to evaluate it as Python code which is what input does.
Try this instead:
chat.py
from socket import *
HOST = ''
PORT = 8000
s = socket(AF_INET, SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print ('Connected by ' + str(addr))
i = True
while i is True:
data = conn.recv(1024)
print ("Received " + repr(data))
reply = str(raw_input("Reply: "))
conn.send(reply)
conn.close()
client.py
from socket import *
HOST = ''
PORT = 8000
s = socket(AF_INET, SOCK_STREAM)
s.connect((HOST, PORT)) # client-side, connects to a host
while True:
message = str(raw_input("Your Message: "))
s.send(message)
print ("Awaiting reply...")
reply = s.recv(1024) # 1024 is max data that can be received
print ("Received " + repr(reply))
s.close()

Python server-client relationship over network problems

I wrote a program for my networking class that measures upload and download speeds by sending a file over a socket and timing the transfer, and I used Python. The problem I'm having is that the server and client can talk just fine when running on the same machine, but as soon as I put the server program on another machine on my network, no file transfer happens. They talk to each other (Client says "connected to server" and server says "connection from xxx.xxx.xxx.xxx") but the file transfer size and speed are shown as 0 and 0.
Here's the server code:
import util
import socket
import os
import shutil
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = ""
port = 12345
f = open("receivedfromclient.txt", "r+")
print "Waiting for clients..."
s.bind((host, port))
s.listen(5)
c, addr = s.accept()
print "Client connected:", addr
start = time.clock()
msg = c.recv(257024)
stop = time.clock()
duration = stop-start
f.write(str(msg))
b = os.path.getsize("receivedfromclient.txt")
print "File size = ", b, "bits"
print "Time to transfer from client = ", duration, " seconds"
bw = (b/duration)/1048576
print "The upload bit rate is ", bw, "Mpbs"
f.close()
shutil.copy("receivedfromclient.txt", "sendtoclient.txt")
f.open("sendtoclient.txt")
c.send(f.read())
f.close()
c.close()
s.close()
and the client code is similar:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = raw_input("Please enter host address: ")#socket.gethostname()
port = 12345
sendfile = raw_input("Please enter name of file to transfer: ")
f = open(sendfile,"rb")
g = open("receivedfromserver.txt","w")
print "Connecting to ", host, port
s.connect((host, port))
s.send(f.read())
and so on. Can anybody tell me what I'm doing wrong here?
Hmm - there are at least some problems:
The major one is, that IMHO it is not clear what you really want to do.
Here is your code with some remarks:
# import util <-- NOT NEEDED
import socket
import os
import shutil
import time # <-- Added
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = ""
port = 12345
f = open("receivedfromclient.txt", "r+")
print "Waiting for clients..."
s.bind((host, port))
s.listen(5)
c, addr = s.accept() # <-- FORGOTTEN ()
print "Client connected:", addr
start = time.clock()
msg = c.recv(257024) # <-- You need some loop here to get the whole file
stop = time.clock()
duration = stop-start
f.write(str(msg))
b = os.path.getsize("receivedfromclient.txt") # <-- = instead of .
print "File size = ", b, "bits"
print "Time to transfer from client = ", duration, " seconds"
bw = (b/duration)/1048576
print "The upload bit rate is ", bw, "Mpbs"
f.close()
shutil.copy("receivedfromclient.txt", "sendtoclient.txt")
f.open("sendtoclient.txt")
c.send(f.read())
f.close()
c.close()
s.close()
One problem here is, that start is in mostly all cases equal to stop - so you get a Division By Zero error in (b/duration).
In the client part at least a import socket is missing; the g is not needed at all.
Please explain further, what you want to do.
If you want to transfer files, there are a lot of ways to do (sftp, rsync, nc, ...).

Categories

Resources