Безопасный протокол для сокетов
От: Holms США  
Дата: 28.11.09 17:42
Оценка:
привет


Делаю я тут сокет сервер. Для приема/отправки сообщений использую свой протокол, такого типа

int PacketTypeId
int PacketLength
byte[] Data;


код для анализа raw socket data такой

    public class BufferParser
    {....

        private readonly MemoryStream _stream = new MemoryStream(1024);
    private readonly byte[] _buffer = new byte[1024];
    public void Parse()
    {
      lock (_stream)
      {
        int step = 0;
        int structLength = -1;

        IParserStruct currentStruct = null;

        //reset stream Position, After writing it points to the end of stream
        _stream.Position = 0;

        while (_stream.Position + 8 <= _stream.Length) //8 cause we need at least 8 bytes to start
        {
          if (step == 0)
          {
            //read Id - it must be always at first place
            _stream.Read(_buffer, 0, 8); //8 bytes for StructId and its Length
            int structId = BitConverter.ToInt32(_buffer, 0);

            Type currentStructType;
            if (!Structs.TryGetValue(structId, out currentStructType))
              throw new BufferParserException(string.Format("Structure with ID = {0} is not supported.", structId));

            currentStruct = (IParserStruct)Activator.CreateInstance(currentStructType);

            //read struct Length
            structLength = BitConverter.ToInt32(_buffer, 4);

            step = 1;
            continue;                     
          }
          if (step == 1)
          {
            if (currentStruct == null || structLength == -1)
              throw new BufferParserException("Got to read the structure, but not created.");
            if (structLength + _stream.Position <= _stream.Length)
            {
              _stream.Read(_buffer, 0, structLength);
              currentStruct.ReadBytes(_buffer, 0);
              //make an additional check to ensure struct was read OK. Not used in this version
              //if (!currentStruct.CrcOk())
              //  throw new BufferParserException("Structure was read, but its CRC is wrong.");

              //if is ok, raise the event that structure was read succesfully
              StructRead(this, currentStruct);

              //go read another structure
              step = 0;
            }
            else
            {
              break; //nothing to read
            }
          }
        }
        if (step == 1)
          _stream.Position -= 8;

        int shiftBufferLength = (int)(_stream.Length - _stream.Position);
        if (shiftBufferLength > 0)
        {
          _stream.Read(_buffer, 0, shiftBufferLength);
          _stream.SetLength(0);
          _stream.Seek(0, SeekOrigin.Begin);
          _stream.Write(_buffer, 0, shiftBufferLength);
        }
        else
        {
          _stream.SetLength(0);
          _stream.Seek(0, SeekOrigin.Begin);
        }
      }
    }


у каждого клиента свой BufferParser, на данный момент всё работает нормально, но иногда приходят "плохие" данные и выбрасывается исколючение BufferParserException, именно из этого и была создана тема
Автор: Holms
Дата: 25.11.09
, никто не предполагал что такое исключение может быть и оно осталось не обработанным.
Щас всё нормально, но интересно как пишутся протоколы которые бы были устойчивы к непредвиденным данным. Блокировать плохие пока IP клиент не разрешает.
Может не стоить изобретать велосипед и есть что-то готовое уже?

Также искал "high-speed scalable TCP/IP server" ничего путного кроме как примеров чата не нашел. Подскажите что используете вы, трудно верится что все пишут свои велосипеды
Смотрел ACE но показалось что оно слишком большое, да и учить другую библиотеку как-то не шибко охота

Спасибо
... << RSDN@Home 1.2.0 alpha 4 rev. 1253>>
The life is relative and reversible.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.