C# TCPListener文件传输

C# TCPListener文件传输,c#,tcpclient,C#,Tcpclient,我遇到了一点小麻烦 我可能不是TCP连接方面的专家,但我希望这里有人能帮助我 这是我的客户代码: void Connect(String server, String message) { try { Int32 port = 8968; TcpClient client = new TcpClient(server, port); Byte[] data = File.Rea

我遇到了一点小麻烦

我可能不是TCP连接方面的专家,但我希望这里有人能帮助我

这是我的客户代码:

    void Connect(String server, String message)
    {
        try
        {
            Int32 port = 8968;
            TcpClient client = new TcpClient(server, port);
            Byte[] data = File.ReadAllBytes(curSelectedFile);
            NetworkStream stream = client.GetStream();


            Byte[] fileData = File.ReadAllBytes(curSelectedFile);
            Byte[] msgData = Encoding.ASCII.GetBytes("SendFile");
            Byte[] sendData = new byte[fileData.Length + msgData.Length];

            // Copy data to send package.
            msgData.CopyTo(sendData, 0);
            fileData.CopyTo(sendData, 4);

            // Send the message to the connected TcpServer. 
            stream.Write(data, 0, data.Length);

            Console.WriteLine("Sent: {0}", message);

            // Receive the TcpServer.response. 

            // Buffer to store the response bytes.
            data = new Byte[256];

            // String to store the response ASCII representation.
            String responseData = String.Empty;

            // Read the first batch of the TcpServer response bytes.
            Int32 bytes = stream.Read(data, 0, data.Length);
            responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
            Console.WriteLine("Received: {0}", responseData);

            // Close everything.
            stream.Close();
            client.Close();
        }
        catch (ArgumentNullException e)
        {
            Console.WriteLine("ArgumentNullException: {0}", e);
        }
        catch (SocketException e)
        {
            Console.WriteLine("SocketException: {0}", e);
        }

        Console.WriteLine("\n Press Enter to continue...");
        Console.Read();
    }
这是我的服务器一:

            // Listen loop.
            while(true)
            {
                using (TcpClient tcpClient = myListener.AcceptTcpClient())
                {
                    Console.WriteLine("[Server] Acceptam client.");
                    using (NetworkStream networkStream = tcpClient.GetStream())
                    {
                        // Buffer for reading data
                        Byte[] bytes = new Byte[1024];
                        var data = new List<byte>();

                        int length;

                        while ((length = networkStream.Read(bytes, 0, bytes.Length)) != 0)
                        {
                            var copy = new byte[length];
                            Array.Copy(bytes, 0, copy, 0, length);
                            data.AddRange(copy);
                        }

                        // Incercam sa vedem ce doreste clientul.
                        string msg = Encoding.ASCII.GetString(data[0], 0, length);
                        if(msg.StartsWith("SendFile"))
                        {
                            using (Stream stream = new FileStream(@"C:\test.mp3", FileMode.Create, FileAccess.ReadWrite))
                            {
                                BinaryFormatter binaryFormatter = new BinaryFormatter();
                                networkStream.Position = 4;
                                binaryFormatter.Serialize(networkStream, data.ToArray());
                            }
                        }
                    }
                }
            }
//侦听循环。
while(true)
{
使用(TcpClient TcpClient=myListener.AcceptTcpClient())
{
Console.WriteLine(“[Server]acceptim客户端”);
使用(NetworkStream NetworkStream=tcpClient.GetStream())
{
//用于读取数据的缓冲区
字节[]字节=新字节[1024];
var data=新列表();
整数长度;
while((长度=networkStream.Read(bytes,0,bytes.length))!=0)
{
var copy=新字节[长度];
复制(字节,0,复制,0,长度);
数据。添加范围(副本);
}
//因为这是一部电影。
string msg=Encoding.ASCII.GetString(数据[0],0,长度);
if(msg.StartsWith(“SendFile”))
{
使用(Stream-Stream=newfilestream(@“C:\test.mp3”、FileMode.Create、FileAccess.ReadWrite))
{
BinaryFormatter BinaryFormatter=新的BinaryFormatter();
networkStream.Position=4;
序列化(networkStream,data.ToArray());
}
}
}
}
}
我在这里要做的是: -我希望客户发送一条消息。。像“SaveFile”&在这个字符串之后是filedata。 -在处理文件之前,服务器应该读取客户机消息,并根据客户机sentstring处理内容

我相信我不知道怎么做

我可以举一个例子说明如何发送/接收和读取文件中的某些字符串吗?如何将它们放入字节数组以及如何读取。。。这真是太难了


PS:当前的服务器代码正在读取数据,可以按照我的编码进行写入,而不会丢失任何包。但他也在写我在转换文件字节之前发送的传统数据包。

networkStream.Position=4不合法,因为
NetworkStream
不可查找

我不鼓励您混合使用文本和二进制数据,因为这会使应用程序协议变得复杂。但是如果您真的想这样做,您应该使用
BinaryWriter
BinaryReader
,因为它可以将字符串写入流中,以后可以读取该字符串,而无需占用字符串后面的字节

然后你可以做这样的事情

在客户端:

BinaryWriter writer = new BinaryWriter(networkStream);

writer.Write("SendFile");
writer.Write(fileData.Length);
writer.Write(fileData);
在服务器中:

BinaryReader reader = new BinaryReader(networkStream);

switch (reader.ReadString())
{
    case "SendFile":
    {
        int length = reader.ReadInt32();
        byte[] fileData = reader.ReadBytes(length);
        // ... then do whatever with fileData, like write to a file
        break;
    }
}
长度计数字符串的
BinaryWriter/Reader
实现是非标准的,因此,如果您想使用此技术与任何其他非.NET代码交互,它将更加复杂,因为您必须自己复制/重新实现非标准长度计数逻辑


更好的方法是将命令编码为固定长度的数据,例如8、16或32位的值,它只是指定命令的某个整数。然后,您可以在代码中以
enum
类型列出您的命令,在网络流中强制转换I/O。这将更便于移植,更易于在非.NET平台上实现。

感谢您的建议,我将尽可能避免在同一数组中传输字符串和二进制文件。