如何设计TCP数据报并发送数据?

时间:2015-01-13 06:58:09

标签: c# tcpclient datagram networkstream payload

大家好,我有服务器的IP和端口号,然后我想使用Socket TcpClient对象来连接服务器来发送和接收数据,但我不知道如何自定义tcp-ip数据报

以下是数据包的描述

name                  bit         datatype
sync_tag              16          uint(16)    const:0xAA 0x55
version               8           uint(8)     const:0x01
packet_length         16          uint(16)    ?
payload_id            8           uint(8)     0x01,0x02,0x03,0x04...(now it is 0x01)
for(int i=0;i<length-8;i++){
payload_data          8           byte(1)      ?
}                                   
CRC16                 16          uint(16)    ?

packet_length:从sync_tag的第一个字节到最后一个字节CRC16 payload_data:现在的结构如下

syntax           bit      datatype   
username         264      char(33)
password         264      char(33)

这是什么方式知道什么是&#34;长度-8&#34;以及如何计算packet_length? 最后我将使用TcpClient和NetwordStream发送byte []?

    >here is the codes I attempt to write
    >I don't know how to send the packet
    [1]: chinafilm.org.cn/uploads/soft/140117/2_1140448191.pdf  
    public static void TestTcpClient()
    {
        TcpClient client = new TcpClient("58.62.144.227", 18080);
        NetworkStream stream = client.GetStream();
        client.LingerState = new LingerOption(true, 30);
        if (!client.Connected)
        {
            Console.WriteLine("Connect Error!");
            return;
        }
        byte[] buffer = new byte[1024];
        //I don't konw what is packet_length,so packetlength is a test sample
        byte[] packetlength = new byte[2];
        //Like packetlength,It is a test sample;
        byte payloadData = byte.MinValue;
        //CRC16 algorithm,I can find some example 
        byte[] crc16 = new byte[2];
        buffer[0] = 0xAA; //sync_tag;
        buffer[1] = 0x55;
        buffer[2] = 0x01; //versin
        buffer[3] = packetlength[0]; //packet_length;
        buffer[4] = packetlength[1];
        buffer[5] = 0x01; //payload_id : If I use the username and password,It is 0x01
        buffer[6] = payloadData;//Contains username and password
        buffer[7] = crc16[0];
        buffer[8] = crc16[1];
        stream.Write(buffer, 0, buffer.Length);
        // Buffer to store the response bytes.
        byte[] 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();
    }

1 个答案:

答案 0 :(得分:1)

您可以使用MemoryStreamBinaryWriter来轻松构建包

    MemoryStream bufferStream = new MemoryStream();
    BinaryWriter writer = new BinaryWriter(bufferStream);
    writer.Write(new byte[] { 0xAA, 0x55, 0x01 });
    writer.Write((ushort)66 + 8); // size of username/password, plus all overheads
    writer.Write((byte) 0x01);
    writer.Write("foouser".PadRight(33, '\0')) // Padding to 33 characters
    writer.Write("foooassword".PadRight(33, '\0')) // Padding to 33 characters
    // calculate CRC
    ushort crc16 = 999;
    writer.Write(crc16);
    // get result
    byte[] result = bufferStream.ToArray();

有关填充的更多信息:C# padding string with n bytes and writing it out

对于CRC,您可以尝试this NuGet package,但我从未使用它。