【问题标题】:NetworkStream cuts off first 4 bytes when readingNetworkStream 在读取时切断前 4 个字节
【发布时间】:2016-06-29 23:03:12
【问题描述】:

我遇到了一个奇怪的问题。当我尝试通过 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('\0'))))
while(bytesReceived < numberOfBytes && (count = clientStream.Read(buffer, 0, buffer.Length)) > 0)
{
    file.Write(buffer, 0, count);
    bytesReceived += count;
}

这里是完整代码的链接 - http://pastebin.com/VwTgTxgb

【问题讨论】:

    标签: c# networkstream tcpsocket


    【解决方案1】:

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

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

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

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

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

    这是一个帮助您入门的 sn-p:

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

    【讨论】:

    • 非常感谢!这适用于 BinaryReader。这只是一个简单的测试示例,不是工作原型,但感谢您指出弱点,这真的很有帮助。
    猜你喜欢
    • 2017-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多