简体   繁体   中英

ValueError: invalid literal for int() with base 10: '' while converting string into int value

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... ie

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 eg CRLF as http does in the request header).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM