【问题标题】:ValueError: invalid literal for int() with base 10: '' while converting string into int valueValueError: int() 以 10 为基数的无效文字:'' 同时将字符串转换为 int 值
【发布时间】:2019-12-07 18:19:00
【问题描述】:

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

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

【问题讨论】:

  • 您需要提供一个完整的、最小的、有效的代码示例。例如,您至少缺少导入语句。 stackoverflow.com/help/minimal-reproducible-example
  • 我不确定为什么会失败 - 但假设您使用的是 TCP 套接字,那么整个方法无论如何都会被破坏。如果发送者发送长度和文件名而不等待响应,那么接收者可能会在一次调用中接收到该数据的 any 前缀:它可能是整个事情,也可能是长度和文件名的一部分,或者它甚至可能不是整个长度。使用单个 .send() 发送的内容与使用单个 .recv() 接收的内容之间绝对没有联系
  • @probat 我现在将编辑它并添加完整的服务器/客户端代码。
  • @jasonharper 先生,使用 tcp socekt 发送和接收文件的正确方法是什么?是的,我的发件人同时发送文件名和文件名长度。
  • 正如@jasonharper 所说 - 接收者可以将所有数据(文件大小和文件内容)作为一个字符串获取。 filesize 转换为字符串可能使用不同的字节数,客户端无法识别字符串的结尾与文件大小和数据的开头。一种方法是在具有大小的字符串之后发送新行,客户端必须读取单个字节直到它获得新行 - 然后将其转换为数字 - 此方法使用 HTTP 来获取标头。或者您可以使用struct() 转换为始终具有 4 个字节的结构,并且客户端始终必须接收 4 个字节才能获取文件大小。

标签: python sockets serversocket tclientsocket


【解决方案1】:

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'

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

请注意,第一个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 在请求标头中所做的那样)。

【讨论】:

    猜你喜欢
    • 2019-06-15
    • 2017-12-06
    • 1970-01-01
    • 2021-12-03
    • 1970-01-01
    • 2013-08-04
    • 2023-03-09
    • 1970-01-01
    相关资源
    最近更新 更多