NetworkStream 在读取时截掉前 4 个字节

NetworkStream cuts off first 4 bytes when reading

我运行遇到了一个st运行ge问题。当我尝试通过 TCP 套接字发送文件时,发送信息的前 4 个字节被截断。

也就是发送和接收的代码。

客户端

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);
}

服务器端

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

这是完整代码的 link - http://pastebin.com/VwTgTxgb

你在这里做的事情非常很奇怪。

首先,文件名的检索可以大大简化为 Path.GetFileName() 调用。

其次,您确定 ASCII 就足够了吗?

第三,将整个文件读入内存对于概念验证项目来说还可以,但要准备好切换到流操作。

第四,你的协议有点靠不住。发送可变大小的有效负载时,需要首先告诉接收方您要发送多少字节。这正是您在发送文件名时不会做的事情。

这里有一个片段可以帮助您入门:

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: 

            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);
                    }
                }
            }
        }
    }
}