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 stream
0x31 '1'
0x31 '1'
0x34 '4'
0x32 '2'
0x62 'b'
0x65 'e'
0x65 'e'
0x72 'r'
0x73 's'
0x2e '.'
0x74 't'
0x78 'x'
0x74 't'
How can the reader know when the length is finished and when the filename starts?
Note that the first recv
call may in theory get just 1
or it could get 1142b
(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.
0x0B 11 (length of filename)
0x34 '4'
0x32 '2'
0x62 'b'
0x65 'e'
0x65 'e'
0x72 'r'
0x73 's'
0x2e '.'
0x74 't'
0x78 'x'
0x74 't'
This way the receiver can use read(1)
to get one byte (the length) and then do another read(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 with send
or it can be a part of the join of multiple send
calls from the writer. If you use recv
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).