我正在开发一个客户端,它使用一个非常简单的协议通过TCP连接生成和传输位图:
为了在开发过程中帮助我,我实现了一个等待连接的简单服务器,在客户端使用随机生成的文件名发送并将其存储在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()) + "'");
}
}
}
}
}
为了测试服务器,我实现了一个生成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的大小。
为什么有效?是否存在隐式Endianness-Detection?如果现在我要在C中实现一个客户端 - 我是否需要担心字节序?如果不是 - 我的服务器期待什么?
答案 0 :(得分:0)
编码参数称为“字符编码”,显然对整数写入流的方式没有影响。
如果您的客户端和服务器具有相同的字节序,那么无论字符编码是什么,代码都可以工作,因为您没有在流中写入任何字符,只是字节。