TCP 传输文件在 1 台 PC 上的服务器和客户端 运行 时有效,但在 2 台 运行 时损坏

TCP transfer file works when server&client are running on 1 PC but corrupts when running on 2

所以我正在尝试制作一个程序,该程序将我想从我的主 PC 中的客户端打印的文件发送到我的第二台运行服务器并连接到打印机的 PC。 当我测试我的代码时,我 运行 我的主电脑上的客户端和服务器运行良好。但是,当我 运行 主 PC 上的客户端和第二台 PC 上的服务器时,文件已损坏,我不确定为什么。

这是我的Listener(我删除了我认为不需要的部分):

void Listener()
{
    //All of these strings and bools are filled correctly I just removed it because its long
    string file="";
    string size = "";
    bool print;

    Socket server = myList.AcceptSocket();

    var output = File.Create(file);
    Console.WriteLine("Client connected. Starting to receive the file");

    int k = 0;
    int read = 0;
    byte[] buffer = new byte[long.Parse(size)];
    NetworkStream stm = new NetworkStream(server);

    while ((k = stm.Read(buffer, 0, buffer.Length-read)) > 0)
    {
        read += k;
    }
    output.Write(buffer, 0, buffer.Length);

    output.Close();
    if (print) { PrintFile(file); }
    server.Close();
    Thread.CurrentThread.Abort();            
}

客户端代码如下(去掉了我认为不需要的部分):

void startClient()
{
    FileInfo f = new FileInfo(file);
    Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    client.Connect(IPAddress.Parse("10.0.0.13"), 27015);
    Console.WriteLine("Connected");
    byte[] bytes = File.ReadAllBytes(file);
    client.SendFile(file);
    Console.WriteLine("File Sent");
    client.Close();
}

有人知道怎么解决吗?提前致谢!

您没有将 read 偏移量应用到缓冲区,在每次 NetworkStream.Read() 调用时从索引 0 开始写入。在本地,或者在使用较小的文件进行测试时,这会很好地工作,因为所有内容都会在一个 Read() 中到达。在真实网络上或处理较大文件时,您会发现需要多次 Read() 调用才能读取所有数据。

所以改成:

stm.Read(buffer, read, buffer.Length-read)

您可能还想重新考虑一次读取内存中的整个文件。您可能希望同时将其写入磁盘,尤其是因为分配大型数组可能会导致 OutOfMemoryException 比您预期的更早。

还可以考虑使用现有的网络协议,而不是自行开发。除了这个非常基本的问题之外,您还容易 运行 陷入许多其他常见的套接字陷阱。