NetworkStream在读取时会切断前4个字节

时间:2016-03-14 18:40:32

标签: c# networkstream tcpsocket

我遇到了一个奇怪的问题。当我试图通过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

1 个答案:

答案 0 :(得分:2)

你在非常做了一些奇怪的事情。

首先,文件名的检索可以大大简化为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: 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);
                    }
                }
            }
        }
    }
}