I am try to send/recv data over socket. I am getting this error while convert string to an integer value. this integer value is the length of filename.
Traceback (most recent call last):
File "C:\Users\Nitesh Rathi\Desktop\clientSocket.py", line 16, in <module>
buff = int(filesize)
ValueError: invalid literal for int() with base 10: ''
Code
sending side
from socket import *
import os
HOST = '192.168.1.7'
PORT = 9999
ADDRESS = (HOST, PORT)
soc = socket(AF_INET, SOCK_STREAM)
soc.bind(ADDRESS)
soc.listen(5)
print('listen for connection...')
conn, addr = soc.accept()
print('got connection from', addr)
filename = 'file1.txt'.encode('utf-8')
fl = len(filename)
fl = str(fl)
print('size of filename :', fl, 'bytes')
conn.send(fl.encode('utf-8'))
print('size of filename sent')
conn.send(filename)
print('filename sent')
filedata = 'this is file1 data'.encode('utf-8')
conn.sendall(filedata)
print('data sent')
conn.close()
soc.close()
print('socket closed')
receiving side
from socket import *
import os
HOST = '192.168.1.7'
PORT = 9999
ADDRESS = (HOST, PORT)
PATH = "C:/Users/Nitesh Rathi/Desktop/RECV"
soc = socket(AF_INET, SOCK_STREAM)
soc.connect(ADDRESS)
print('connected to', ADDRESS)
while True:
filesize = soc.recv(255).decode('utf-8')
buff = int(filesize)
print("size of filename: ", filesize, 'bytes')
filename = soc.recv(buff).decode('utf-8')
if not filename: break
Path = os.path.join(PATH, filename)
print(Path)
file = open(Path, 'wb')
filedata = soc.recv(1024)
file.write(filedata)
file.close()
soc.close()
print('socket closed')
print('data recvd')
TCP stream sockets implement a stream protocol, not a message protocol and the received must therefore know in advance how many bytes it should receive.
Your code is sending the filename length as a string, followed by the length and this is an ambiguous protocol... for example if the filename is
42beers.txt
your code will write to the streamHow can the reader know when the length is finished and when the filename starts?
Note that the first
recv
call may in theory get just1
or it could get1142b
(because it's a byte stream channel, not a message channel).The error you are getting is probably because of this second possibility.
For example an alternative approach that could work if your filenames are never bigger than 255 bytes in length is to write a single byte to represent the length of the string, followed by the string... i.e.
This way the receiver can use
read(1)
to get one byte (the length) and then do anotherread(sz)
to get the filename.To recap
recv
gives you whatever was received so far from the network and it can be less than what the sender passed withsend
or it can be a part of the join of multiplesend
calls from the writer. If you userecv
then you must do a loop that keeps accumulating until the data has been received (and you must know how much that is or you must use separators like e.g. CRLF as http does in the request header).