在BinaryReader中是否有自动的端序检测?

本文关键字:检测 BinaryReader 是否 | 更新日期: 2023-09-27 18:14:59

我正在开发一个客户端,它使用一个非常简单的协议通过TCP连接生成和传输位图:

  • [步骤1]发送文件大小为n的字节作为Int64
  • [步骤2]发送n个字节表示位图数据

为了在开发过程中帮助我,我实现了一个简单的服务器,它等待连接,在客户端发送文件时接受文件,并使用随机生成的文件名

将它们存储在HDD上
using System;
using System.Text;
using System.IO;
using System.Net.Sockets;
namespace SimplePictureReceiverServer
{
    class Program
    {
        private static Int32 PORT = -1;
        private static String DirSaveTo = null;
        static void Main(string[] args)
        {
            // Ensuring that required parameters have been provided
            if (args.Length < 2) { ShowUsage("Parameter-Count"); return; }
            if (!Int32.TryParse(args[0], out PORT)) { ShowUsage("<port>"); return; }
            if (!Directory.Exists(args[1])) { ShowUsage("<dir>"); return; }
            PORT = Int32.Parse(args[0]);
            DirSaveTo = args[1];
            // Setting up the Server on <127.0.0.1>:<PORT>
            TcpClient c = null; NetworkStream s;
            TcpListener l = new TcpListener(System.Net.IPAddress.Loopback, PORT); 
            l.Start();
            while(true)
            {
                // Waiting for a Client to connect
                Console.Write("Waiting ... ");  
                c = l.AcceptTcpClient();
                s = c.GetStream();
                Console.WriteLine("Ok");
                // Handle the client
                try
                {
                    using (BinaryReader r = new BinaryReader(s, Encoding.Unicode))
                    {
                        HandleClient(r);
                    }
                }
                catch(Exception e)
                {
                    Console.WriteLine("Client disconnected (" + e.Message + ")");
                    Console.WriteLine();
                }
            }
        }
        private static void ShowUsage(String s)
        {
            Console.WriteLine("Problem with " + s);
            Console.WriteLine();
            Console.WriteLine("USAGE 't program.exe <port> <dir>");
            Console.WriteLine("<port> : Port to listen to when waiting for connections");
            Console.WriteLine("<dir>  : Directory to store received pictures at. The directory must exist");
            Console.WriteLine();
            Console.WriteLine("Press [ENTER]");
            Console.ReadLine();
        }
        private static void HandleClient(BinaryReader r)
        {
            const Int32 BUF_SIZE = 10 * 1024;
            Int32 cntPicutresReceived = 0; StringBuilder b = new StringBuilder();
            Random rnd = new Random();
            Byte[] buf;
            Int32 bytesLeftToRead;
            while (true)
            {
                using (MemoryStream m = new MemoryStream())
                {
                    // Reading picture size and picture from stream
                    bytesLeftToRead = Convert.ToInt32(r.ReadInt64());               // Reading size as Int32
                                                                                    // Little/ Big Endian - Consider !
                    Console.WriteLine("Expected filesize is " + bytesLeftToRead.ToString("#,##0") + " Bytes");
                    while (bytesLeftToRead > 0)                                      // Reading the picture
                    {
                        buf = r.ReadBytes(Math.Min(BUF_SIZE, bytesLeftToRead));
                        m.Write(buf, 0, buf.Length);
                        bytesLeftToRead = bytesLeftToRead - buf.Length;
                    }
                    // Storing picture on HDD with a fancy filename created in the StringBuilder
                    m.Seek(0L, SeekOrigin.Begin);
                    b.Clear();
                    b.Append((++cntPicutresReceived).ToString("0000"));
                    b.Append("__");
                    b.Append(rnd.Next(Int32.MaxValue).ToString("X"));
                    b.Append(".bmp");
                    using (FileStream f = new FileStream(Path.Combine(DirSaveTo, b.ToString()), FileMode.Create))
                    {
                        m.CopyTo(f);
                    }
                    Console.WriteLine("Image saved at '" + Path.Combine(DirSaveTo, b.ToString()) + "'");
                }
            }
        }
    }
}

为了测试服务器,我实现了一个test - client,它生成5个随机位图并将它们发送到服务器

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Net.Sockets;
namespace SimplePictureSender
{
    class Program
    {
        static Random Random = new Random();
        static void Main(string[] args)
        {
            Bitmap b;
            TcpClient c = new TcpClient("127.0.0.1", 12345);
            Stream s = c.GetStream();
            using (BinaryWriter w = new BinaryWriter(s))
            {
                for (Int32 i = 0; i < 5; i++)
                {
                    using (MemoryStream m = new MemoryStream())
                    {
                        b = CreateRandomBitmap(640, 480, 1000, 1000); b.Save(m, ImageFormat.Bmp);
                        Console.WriteLine("Picture size is " + m.Length + " Bytes"); Console.WriteLine();
                        m.Seek(0L, SeekOrigin.Begin);
                        w.Write(m.Length);
                        m.WriteTo(w.BaseStream);
                    }
                }
            }
            Console.WriteLine("[ENTER] to exit");
            Console.ReadLine();
        }
        private static Bitmap CreateRandomBitmap(Int32 minX = 100, Int32 minY = 100, Int32 maxDeltaX = 250, Int32 maxDeltaY = 250)
        {
            Console.Write("Generating Picture ... ");
            Bitmap b = new Bitmap(Random.Next(minX, minX + maxDeltaX), Random.Next(minY, minY + maxDeltaY));
            Color c;
            for(Int32 x = 0; x < b.Width; x++)
                for(Int32 y = 0; y < b.Height; y++)
                {
                    c = Color.FromArgb(Random.Next(0, 256), Random.Next(0, 256), Random.Next(0, 256));
                    b.SetPixel(x, y, c);
                }
            Console.WriteLine("Done");
            return b;
        }
    }
}

这一切都工作得很好…出奇的好。

如果我将服务器上的using (BinaryReader r = new BinaryReader(s, Encoding.Unicode))行替换为以下内容之一

  • using (BinaryReader r = new BinaryReader(s, Encoding.BigEndianUnicode))
  • using (BinaryReader r = new BinaryReader(s))

设置总是成功地传输和存储位图。然而,我希望这些代码中至少有一个失败,因为服务器应该无法正确提取以下数据blob的大小。

为什么它工作?是否有一个隐含的端序检测?如果现在我要用C语言实现客户端,我需要担心端序吗?如果不是,我的服务器期望什么?

在BinaryReader中是否有自动的端序检测?

参见BinaryReader构造函数。

encoding形参称为"字符编码",显然对如何将整数写入流没有影响。

如果您的客户端和服务器端具有相同的端序,那么无论字符编码是什么,代码都可以工作,因为您没有向流写入任何字符,只是字节。