TCPListener文件传输

时间:2014-11-14 05:54:46

标签: c# tcpclient

我遇到了一点点并发症。

我可能不是TCP Connections的专家,但我希望有人能帮到我。

这是我的客户代码:

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

我在这里尝试做什么: - 我希望客户端发送消息..如“SaveFile”&amp;在此字符串之后是filedata。 - 在对文件执行某些操作之前,服务器应该读取客户端消息并根据客户端sentstring处理内容。

我相信我不知道该怎么做。

我是否有一个关于如何从文件的开始发送/接收和读取某些字符串的示例?我怎么能把它们放在字节数组中以及如何读取它......这是非常压倒性的......

PS:当前的服务器代码正在读取数据,并且在我编码时写入CAN,而不会丢失任何软件包。但他也在编写我转换文件字节之前发送的附加数据包。

1 个答案:

答案 0 :(得分:0)

networkStream.Position = 4;不合法,因为NetworkStream不可搜索。

我会阻止你混合使用文本和二进制数据,因为它在应用程序协议中会产生复杂性。但是如果你真的想这样做,你应该使用BinaryWriterBinaryReader,因为它可以将字符串写入流,然后可以在不消耗字符串后的字节的情况下读取。

然后你可以这样做......

在客户端:

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平台上实现。