Безопасно маркиране на началото/края на пакета за TCP / UDP предаване

Пиша клиент/сървър базирано приложение, което работи в локална мрежа, за обмен на данни между клиент и сървър, създадох много прост NetworkCommand обект, който се преобразува в byte[] и се изпраща с TCP или UDP.

Проблемът е правилното маркиране на end-of-packed,

точно сега използвах byte[] {0, 0, 0} и маркер за край на пакета, но изглежда, че това се повтаря твърде много пъти в самия пълен пакет.

И така, как да маркирам безопасно end-of-packet?

NetworkCommand.cs

using System;
using System.IO;

namespace Cybotech.Common
{
    public enum CommandType
        {
            NeedIP = 1,
            IPData = 2,
        }

    public class NetworkCommand
    {
        public NetworkCommand(CommandType type, byte[] data)
        {
            Command = type;
            Data = data;
        }

        public int Length
        {
            get { return Data.Length; }
        }

        public byte[] Data { get; set; }
        public CommandType Command { get; set; }

        public byte[] ToBytes()
        {
            MemoryStream stream = new MemoryStream();

            //write the command type
            byte[] data = BitConverter.GetBytes((int) Command);
            stream.Write(data, 0, data.Length);

            //append the length of the data
            data = BitConverter.GetBytes(Length);
            stream.Write(data, 0, data.Length);

            //write the data
            stream.Write(Data, 0, Data.Length);

            //end of packer marker
            data = new byte[] {0, 0, 0};
            stream.Write(data, 0, 3);

            data = stream.ToArray();
            stream.Close();
            stream.Dispose();
            return data;

        }

        public static NetworkCommand CreateNetworkCommand(byte[] bytes)
        {
            MemoryStream stream = new MemoryStream(bytes);
            BinaryReader reader = new BinaryReader(stream);

            CommandType type = (CommandType) reader.ReadInt32();
            int length = reader.ReadInt32();
            byte[] data = reader.ReadBytes(length);
            byte[] endMarker = reader.ReadBytes(3);

            NetworkCommand cmd = new NetworkCommand(type, data);
            reader.Close();
            stream.Close();
            stream.Dispose();
            return cmd;

        }

    }
}

person Parimal Raj    schedule 08.06.2013    source източник


Отговори (1)


Една от стратегиите е да започнете пакета с, да речем, 4-байтово число, което представлява размера на пакета, и да го последвате с подходящия брой байтове данни за полезен товар. Тогава знаете точно колко данни трябва да прочетете от приемащия край.

TCP е надежден протокол, така че не трябва да се притеснявате твърде много за синхронизацията. От друга страна, той е ориентиран към потока и тъй като използвате пакетно базиран приложен слой, може да ви е по-лесно да използвате UDP, който е ориентиран към съобщения.

Ако използвате UDP, можете да използвате 4-байтова дължина, последвана от произволен "начален" знак (като [), след това полезния товар и накрая знак "стоп" (като ]). Ако прочетете пакет, който не завършва със знака за спиране, можете да го отхвърлите и да продължите да изхвърляте данни до следващия знак за спиране. Но тогава ще ви трябва начин да помолите подателя да препредаде изгубените данни.

Един добър протокол използва основните слоеве, така че няма да е необходимо да дублирате техните функции.

person Adam Liss    schedule 08.06.2013
comment
така или иначе, трябва да маркирам начален хедър или краен маркер? - person Parimal Raj; 08.06.2013