i have these lines of code for sending and receving from a UDP socket in python3.4, in which i want to send a file from a user to the other.
This is the server side code:
...
data = file.read(1024)
n = int(fileSize / 1024) + 1
for i in range(n):
if(self.sock.sendto(data.encode(), ('127.0.0.1',int(self.nextUserPort)))):
print ("Sending ...")
data = file.read(1024)
print ("File has been Sent Completely!!!")
self.sock.sendto("END#".encode(), ('127.0.0.1',int(self.nextUserPort)))
And this is the client side code:
....
d = self.sock.recvfrom(1024)
data = d[0].decode()
addr = d[1]
try:
while (data.strip().find("END#") != 0) :
file.write(data.decode())
time1 = time.time()
data, addr = self.sock.recvfrom(1024)
time2 = time.time()
print ("download speed is "+ str(1.0/(time2-time1))+" kbps")
print ("File Downloaded Completely!!!!!")
except socket.timeout :
file.close()
self.sock.close()
But when i run the code i get the below error for the line f(self.sock.sendto(data.encode(), ('127.0.0.1',int(self.nextUserPort)))):
AttributeError: 'bytes' object has no attribute 'encode'
And when i remove the encode i get another error that when i searched it i got that i must encode it in python3.4.
The exception is telling you what the problem is:
AttributeError: 'bytes' object has no attribute 'encode'
And as it happens you want to send bytes, so no need to convert anything in this line.
"END#".encode() can be directly written as b"END#".
Unrelated to your question: You might want use a TCP socket or give the transfer some logic to cope with reordered, lost and duplicated packages.
Related
I am trying to create a UDP client-server from a TCP one. I ran into an issue with encoding and printing my receiving message from the server to the client. It works the way I have it on TCP but doesn't seem to work on UDP and I am not sure on what else I have to encode?
Here is the error I am getting:
File "/Users/PycharmProjects/UDPProject/client.py", line 29, in <module>
print("received %s" % command)
TypeError: not all arguments converted during string formatting
And here is my client code with some code cut out.
while True:
message = input("Please enter a command:\n") # ask user to input message
if message == 'quit':
break
if len(message) == 0:
print("Please enter something")
message = input("Please enter a command:\n")
print("Sending %s" % message)
sock.sendto((message.encode("utf-8")), address) # send message
command = str(sock.recvfrom(BUFFER_SIZE), "utf-8")
print("received %s" % command)
print("closing connection with server")
sock.close()
It is happening when the socket is trying to receive from the buffer size in utf-8 format and when I try to print it.
EDIT: I fixed the error, it was just typo as outlined by lenz but now it gives me this error
command = str(sock.recvfrom(BUFFER_SIZE), "utf-8")
TypeError: decoding to str: need a bytes-like object, tuple found
I am not sure why???
socket.recvfrom returns a tuple of pair (bytes, address) in UDP so I had to decode the first item of bytes. This is how I did it.
command = str(sock.recvfrom(BUFFER_SIZE)[0], "utf-8"). The [0] grabs the first item in the tuple of BUFFER_SIZE
import socket
def Main():
host = '127.0.0.1'
port = 5001
server = ('127.0.0.1',5000)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host, port))
message = input("-> ")
while message != 'q':
s.sendto (message, server)
data, addr = s.recvfrom(1024)
print ('Received from server: ' + (data))
message = input("-> ")
s.close()
if __name__ == '__main__':
Main()
When I run this code the line s.sendto (message, server) causes a TypeError: a bytes-like object is required, not 'str'.
How do you fix this kind of problem? I tried searching the internet but can't find a solution.
Sockets read and write bytes, not strings (that's a property of sockets in general, not a python-specific implementaiton choice). That's the reason for the error.
Strings have an encode() methods that transforms them to byte-objects. So, instead of writing my_text, write my_text.encode() to your socket.
Similarly, when you read for the socket, you get a bytes-like object, on which you can call input_message.decode() to convert it into string
The error is due to the fact you are not encoding the message.
Just change:
c.sendto(message, server)
to
c.sendto(message.encode(), server)
in your code.
Example:
import socket
s=socket.socket()
port=12345
s.bind(('',port))
print("Socket bind succesfully")
s.listen(5)
// note this point
message="This is message send to client "
while True:
c,addr=s.accept()
// here is error occured
c.send(message)
c.close()
This is will result in an error message:
c.send(message)
TypeError: a bytes-like object is required, not 'str'
and in order to fix it, we need to change:
c.send(message)
to
c.send(message.encode())
I have created a TCP multithreading webserver but it gives me the following
If the file is found
1. It says "int obj has no attribute encode"
2. Later, it will show list index out of range
If the file is not found
1. It does not display the html error message on the web browser
2. Later, it will show list index out of range
My server code is
import socket
import threading
import os
import sys
#to convert bytes into string
def bytestoString(stringToRead):
stringToRead = bytes.decode(stringToRead)
type(stringToRead)
return(stringToRead)
#to conver string into bytes
def stringToBytes(bytesToSend1):
bytesToSend1= str.encode(bytesToSend1)
type (bytes)
return(bytesToSend1)
#to retreive a file
def retrFile(name,sock):
message=sock.recv(1024)
message_string = bytestoString(message)
print(message_string)
fileName=message_string.split()[1]
fileName=fileName.split("/")[1]
#stringLength=len(fileName)
print(fileName)
if os.path.isfile(fileName):
print ('Ready to send the file................')
with open(fileName,'rb') as fileRead:
data= fileRead.read()
print (data)
exists_Bytes=stringToBytes('HTTP/1.1 200 OK\nContent-type=text/html')
sock.send(exists_Bytes)
for i in range(0 ,len(data)):
sock.send((data[i]).encode())
print('file sent succesfully')
sock.close()
else :
httpResponse=stringToBytes('HTTP/1.1 404 not Found')
sock.send(httpResponse)
#errorDisplayPage=stringToBytes('<html><title>404 Error</title><body>404 Error- Page cannot be found </body></html>')
sock.send(b'<html><title>404 Error</title><body>404 Error- Page cannot be found </body></html>')
print ('error message displayed')
sock.close()
def Main(serverPort):
#creating a server socket type TCP
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
localHost=socket.gethostname()
#binding the server to the client
serverSocket.bind((localHost,serverPort))
serverSocket.listen(5)
print ('***Server is ready to recieve***')
while True:
connectionSocket, addr = serverSocket.accept()
print ('got connection from:<', addr,'>')
t=threading.Thread(target=retrFile,args=('retrThread',connectionSocket))
t.start()
connectionSocket.send('thank you for connecting')
connectionSocket.close()
if __name__ == '__main__':
#getting server hostname and port number from the user
serverPort=int(sys.argv[1])
Main(serverPort)
You have opened your file as binary in your code:
with open(fileName,'rb') as fileRead:
data= fileRead.read()
However, later you try to do some funny things. Now, this differs in Python 2 and 3.You are using Python 3, so this following block is problematic:
for i in range(0 ,len(data)):
sock.send((data[i]).encode())
In python 2 you would iterate over individual chars and it would work fine. However, in python 3 you are iterating over a bytes object, so data[i] will be an int object.
Instead you can just:
sock.sendall(data)
Also according to wikipedia, the HTTP-protocol assumes that the status line is followed by an empty line. That is why you do not see the error message, and will not see the file.
So, postfix your status codes with "\n\n", so like: 'HTTP/1.1 404 not Found\n\n'. The same goes for the OK-message.
Got code from http://www.binarytides.com/python-socket-programming-tutorial/ and changed it to work in python 3.5. It looks like this:
#Socket client example in python
import socket #for sockets
import sys #for exit
#create an INET, STREAMing socket
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
print ('Failed to create socket')
sys.exit()
print ('Socket Created')
host = 'www.google.com';
port = 80;
try:
remote_ip = socket.gethostbyname( host )
except socket.gaierror:
#could not resolve
print ('Hostname could not be resolved. Exiting')
sys.exit()
#Connect to remote server
s.connect((remote_ip , port))
print ('Socket Connected to ' + host + ' on ip ' + remote_ip)
#Send some data to remote server
message = ("GET / HTTP/1.1\r\n\r\n")
try :
#Set the whole string
s.sendall(str(message))
except socket.error:
#Send failed
print ('Send failed')
sys.exit()
print ('Message send successfully')
#Now receive data
reply = s.recv(4096)
print (reply)
and the shell is giving the error "TypeError: a bytes-like object is required, not 'str'" on line 36 where the code is s.sendall(str(message)). Since I'm trying to get into socket programming for a school project I'm really not sure what the error means and haven't found a good example of how to solve it.
The socket().sendall method expects a "bytes-like object", which means a bytes object (or a bunch of other types like memoryview). You are passing a str object, which represents a unicode string, to that method.
To fix this error, you need to encode your message with message.encode(<encoding>) or bytes(message,<encoding>).
Basically trying to use client to send coordinates of a character on the screen and then broadcast that to the other client so it draws the character on the screen.
Yet i'm getting the following errors:
Client Side: s.send((y))
Server Side: ValueError: invalid literal for long() with base 10
Client Code that i get error on:
def updatecoords(task):
s.send(name)
print 'Name sent...'
def updatepos(task):
y = format(Cat.getPos())
s.send((y))
print 'Position sent'
return Task.cont
def readServer(task):
try:
data = s.recv(1024)
print data
except:
print 'no data received'
return Task.cont
Server Code that i get error on:
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((HOST,PORT))
server_socket.listen(1)
conn, addr = server_socket.accept()
print('Someone connected.He :%s%addr')
while True:
data = conn.recv(1024)
if not data:
break
data = pickle.loads(data) # Or json.loads(data)
print "Got id: {message_id}, data: {message}".format(**data)
You are trying to unpickle the received data:
data = pickle.loads(data)
But you are not pickling the data before sending it:
y = format(Cat.getPos())
s.send((y))
Also you have to decide which serialization protocol you wan't to use because pickle and json are not compatible and this comment:
# Or json.loads(data)
suggests that you think both pickle and json should be able to deserialize received data.
So instead of using format you should make your client function similar to this:
def updatepos(task):
y = pickle.dumps(Cat.getPos())
s.sendall(y)
print 'Position sent'
But still this server code:
data = pickle.loads(data)
print "Got id: {message_id}, data: {message}".format(**data)
will work only under two conditions:
- class Cat is imported on server side, otherwise pickle.loads will throw UnpicklingError since pickle protocol preserves class name and unpickling restores the object of class Cat but it can't be done if definition of this class is unavailable
- Cat.getPos() returns a dict (or dict-like object) with keys message_id and message, otherwise format(**data) will throw ValueError if data can't be used as dict or KeyError if one of the mentioned keys is missing in dict
You should also notice that I've replaced s.send((y)) with s.sendall(y) since the first one doesn't guarantee that all data will be sent as documentation says https://docs.python.org/2/library/socket.html#socket.socket.send
I've also dropped additional brackets around y - this doesn't change anything but they are not needed.
As you have posted only part of your code, I was only able to resolve issues present in the posted code sample.