python-3.x - 使用 VB.Net 通过 TCP 发送文件并使用 Python3.6 中的 Socket 接收时出现文件编码错误

标签 python-3.x vb.net tcp file-transfer

我在 VB.Net 中有一个使用 ZipFile.CreateFromDirectory("temp/", "payload.zip", CompressionLevel.Optimal, True) 创建的 zip 文件我发送到我的python服务器:

Dim payload() As Byte = System.Text.Encoding.UTF8.GetBytes(System.Convert.ToBase64String(System.IO.File.ReadAllBytes("payload.zip")))
Dim payloadstr As String = byteArrToString(payload)
Dim client As New TcpClient("192.168.0.160", 42069)
Dim PayloadWriter As New StreamWriter(client.GetStream())

PayloadWriter.Write(payloadstr)
PayloadWriter.Flush()
PayloadWriter.Close()
client.Close()
byteArrToString()功能看起来像:

Public Function byteArrToString(ByVal arr() As Byte) As String

    Return System.Text.Encoding.Unicode.GetString(arr)

End Function

在 python 服务器端,我的代码如下所示:
import socket               # Import socket module
import random,string,io

def randomString(stringLength=10):
 letters = string.ascii_lowercase
 return ''.join(random.choice(letters) for i in range(stringLength))

s = socket.socket()         # Create a socket object
host = "192.168.0.160"      # Define Hostname
port = 42069                # Reserve a port for your service.
s.bind((host, port))        # Bind to the port
s.listen(5)                 # Now wait for client connection.
irName = randomString(10) + ".zip"
ir = io.open(irName,"wb")
print ("Listening now")
while True:
    c, addr = s.accept()    # Establish connection with client.
    print ('Got connection from', addr)
    print ("Receiving Data...")
    print ("Writing as " + irName)
    l = c.recv(4096)
    while (l):
        ir.write(l)
        l = c.recv(4096)
    ir.close()
    c.close()
    print ("Done receiving")

不知何故,我在服务器端收到的 Payload.zip 的大小是 Windows 中 Payload.zip 的两倍,系统拒绝将其识别为有效的 ZIP 文件。我究竟做错了什么?

最佳答案

说明

您在 VB.NET 端对字符串编码进行了大量处理,在这种情况下您确实不应该也不需要这样做。为了帮助您了解正在发生的事情,这里概述了您的代码现在所做的事情:

VB.NET

  • 将压缩文件作为字节数组读入内存。
  • 将字节数组转换为 Base64 编码的字符串。
  • 将 Base64 字符串直接转换为字节数组(注意:这与步骤 1 中的数组不同)。
  • 再次将该字节数组转换回字符串,但这次使用 UTF-16/Unicode 编码。
  • 使用 StreamWriter 将其发送到 Python 端,它可能会也可能不会在流的开头添加 BOM。

  • Python
  • 接收从 VB.NET 发送的数据。
  • 将其写入文件。

  • 在 Python 中,您没有做任何事情来反转您在 VB.NET 代码中采取的步骤,所以这就是数据不同的原因。

    从第 3 步开始,您还使用了一个完全不同的字节数组,它不再代表压缩文件的原始数据,而是它的 Base64 编码版本。一般来说,Base64 通常会将数据大小增加约 1.5 倍,这就是您看到大小增加的原因。

    严格来说,在这种情况下,您需要在 Python 端执行以下操作来反转该过程:
  • 获取所有接收到的数据(在 Python 中是一个字符串)。
  • 从 Base64 解码。
  • 写入文件。

  • 编码之间的切换(第 4 步中的 UTF-8 到 16/Unicode)不应该对数据本身有太大影响,因为它主要影响字符串的显示方式,因此这实际上并不是您需要反转的。

    答案

    我猜你在 VB.NET 端做所有与字符串相关的工作的原因是因为 Python 套接字将其数据作为字符串处理。但是您应该知道,在后台(即使在 Python 中),字符串始终是一个字节数组,无论如何。

    我理解这种混淆,我以前见过很多次,但编码主要只是一种存储和/或显示文本的方式。丢失数据的唯一方法是尝试使用不兼容的编码显示数据。但在这种情况下,您不是在处理文本,而是在处理原始数据。因此,只要您不尝试通过字符串显示或操作它,就完全没有必要对其进行转换。

    您(应该)需要做的就是获取从 File.ReadAllBytes() 返回的字节数组。并将其直接发送到 Python。

    Dim payload() As Byte = System.IO.File.ReadAllBytes("payload.zip")
    
    Using client As New TcpClient("192.168.0.160", 42069)
        Using stream As NetworkStream = client.GetStream()
            stream.Write(payload)
        End Using
    End Using
    
    Using/End Using块负责为您关闭和处理对象。

    关于python-3.x - 使用 VB.Net 通过 TCP 发送文件并使用 Python3.6 中的 Socket 接收时出现文件编码错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59428002/

    相关文章:

    tcp - 在 TCP 中,发送纯 ACK 时 SEQ 编号/SND.NXT 是否递增

    Python:将正整数和负整数的列表元素字符串转换为int?

    vb.net - 将焦点设置到 Web 浏览器控件中的 HTML 文本框和按钮

    python - 崩溃可能是因为 pygame

    c# - 是否可以在 WinForms .Net 的组件设计器中更改组件名称

    c# - 为什么 VB.NET 9 不像 C# 3 那样具有自动属性?

    c# - 为什么 dot42 C# android 中缺少 "using Net.Sockets "?

    c# - 指示远程主机已关闭连接的 NetworkStream.Read 的替代方法?

    arrays - Numpy 迭代和追加

    python - 是否可以在列表和元素中使用相同的切片符号来获得相同的结果?