简体   繁体   English

读取时NetworkStream会截断前4个字节

[英]NetworkStream cuts off first 4 bytes when reading

I ran into a strange problem. 我遇到一个奇怪的问题。 When I'm trying to send the file via a TCP socket, the first 4 bytes of sended information cuts off. 当我尝试通过TCP套接字发送文件时,发送的信息的前4个字节被切断。

That is sending and receives pieces of code. 那就是发送和接收代码。

Client side 客户端

for (var i = 0; i < fileContentByte.Length; i += buffer.Length)
{
    var size = (i + buffer.Length > fileContentByte.Length) ? fileContentByte.Length - i : buffer.Length;
    clientSocket.Write(fileContentByte, i, size);
}

Server side 服务器端

using(var file = File.Create("C:\\test\\"+fileName.Substring(0, fileName.IndexOf('\0'))))
while(bytesReceived < numberOfBytes && (count = clientStream.Read(buffer, 0, buffer.Length)) > 0)
{
    file.Write(buffer, 0, count);
    bytesReceived += count;
}

Here is link on full code - http://pastebin.com/VwTgTxgb 这是完整代码的链接-http://pastebin.com/VwTgTxgb

You're doing something very strange here. 您在这里做的事情奇怪。

First of all, retrieval of file name can be greatly simplified down to Path.GetFileName() call. 首先,可以极大地简化到Path.GetFileName()调用的文件名检索。

Second, are you sure ASCII will suffice? 第二,您确定ASCII足够吗?

Third, reading the entire file into memory is OK-ish for a proof-of-concept project, but be ready to switch to streaming operations. 第三,对于概念验证项目来说,将整个文件读入内存是可以的,但是准备切换到流操作。

Fourth, your protocol is somewhat wonky. 第四,您的协议有些古怪。 When sending variable-size payload, it is required to first tell the receiving party exactly how much bytes are you going to send. 在发送可变大小的有效负载时,需要先告知接收方确切的发送多少字节。 This is exactly what you don't do when sending file name. 这正是发送文件名时不执行的操作。

Here's a snippet to get you started: 以下是帮助您入门的代码段:

using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace FolderSync
{
    class Program
    {
        static void Main()
        {
            var server = new Server();
            server.Start();

            new Client().TransmitFile(
                new IPEndPoint(IPAddress.Loopback, 35434), 
                @"f:\downloads\ubuntu-14.04.3-desktop-amd64.iso");

            Console.ReadLine();

            server.Stop();
        }
    }

    class Server
    {
        private readonly TcpListener tcpListener;

        public Server()
        {
            tcpListener = new TcpListener(IPAddress.Loopback, 35434);
        }

        public void Start()
        {
            tcpListener.Start();
            tcpListener.BeginAcceptTcpClient(AcceptTcpClientCallback, null);
        }

        public void Stop()
        {
            tcpListener.Stop();
        }

        private void AcceptTcpClientCallback(IAsyncResult asyncResult)
        {
            //
            // Big fat warning: http://stackoverflow.com/a/1230266/60188

            tcpListener.BeginAcceptTcpClient(AcceptTcpClientCallback, null);

            using(var tcpClient = tcpListener.EndAcceptTcpClient(asyncResult))
            using(var networkStream = tcpClient.GetStream())
            using(var binaryReader = new BinaryReader(networkStream, Encoding.UTF8))
            {
                var fileName = binaryReader.ReadString();
                var length = binaryReader.ReadInt64();

                var mib = length / 1024.0 / 1024.0;
                Console.WriteLine("Receiving '{0}' ({1:N1} MiB)", fileName, mib);

                var stopwatch = Stopwatch.StartNew();

                var fullFilePath = Path.Combine(Path.GetTempPath(), fileName);
                using(var fileStream = File.Create(fullFilePath))
                    networkStream.CopyTo(fileStream);

                var elapsed = stopwatch.Elapsed;

                Console.WriteLine("Received in {0} ({1:N1} MiB/sec)", 
                    elapsed, mib / elapsed.TotalSeconds);
            }
        }
    }

    class Client
    {
        public void TransmitFile(IPEndPoint endPoint, string fileFullPath)
        {
            if(!File.Exists(fileFullPath)) return;

            using(var tcpClient = new TcpClient())
            {
                tcpClient.Connect(endPoint);

                using(var networkStream = tcpClient.GetStream())
                using(var binaryWriter = new BinaryWriter(networkStream, Encoding.UTF8))
                {
                    var fileName = Path.GetFileName(fileFullPath);
                    Debug.Assert(fileName != null, "fileName != null");

                    //
                    // BinaryWriter.Write(string) does length-prefixing automatically
                    binaryWriter.Write(fileName);

                    using(var fileStream = File.OpenRead(fileFullPath))
                    {
                        binaryWriter.Write(fileStream.Length);
                        fileStream.CopyTo(networkStream);
                    }
                }
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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