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

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

我正在尝试 send/recv 通过套接字传输数据。将字符串转换为整数值时出现此错误。这个整数值是文件名的长度。

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: ''

代码

发送方

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')

接收端

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 流套接字实现的是流协议,而不是消息协议,因此接收端必须事先知道它应该接收多少字节。

您的代码将文件名长度作为字符串发送,后跟长度,这是一个不明确的协议...例如,如果文件名是 42beers.txt 您的代码将写入流

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'

reader 如何知道长度何时结束以及文件名何时开始?

请注意,第一个 recv 调用理论上可能只得到 1 或者它可能得到 1142b (因为它是字节流通道,而不是消息通道)。

您遇到的错误可能是因为第二种可能性。

例如,如果您的文件名长度不超过 255 个字节,另一种可行的方法是写入一个字节来表示字符串的长度,然后是字符串...即

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'

这样接收方可以使用 read(1) 获取一个字节(长度),然后使用另一个 read(sz) 获取文件名。

总而言之,recv 为您提供到目前为止从网络接收到的任何内容,它可以小于发送方通过 send 传递的内容,或者它可以是多个 send 作者来电。如果你使用 recv 那么你必须做一个不断累积的循环,直到收到数据(你必须知道那是多少,或者你必须使用分隔符,例如 CRLF,就像 http 在请求中所做的那样 header).