Вернуться   CoderX :: Forums > Основные форумы > Программинг
Войти через OpenID

Программинг Форум для тем связанных с программированием

Чат (Новых сообщений с момента вашего последнего визита нет)
Загрузка...
Задавайте ваши вопросы на форуме. Чат предназначен для небольших разговоров.
 
Ответ
 
Опции темы Опции просмотра
Старый 05.02.2012, 22:30   #1
Местный
 
Регистрация: 23.02.2009
Сообщений: 319
Сказал Спасибо: 72
Имеет 60 спасибок в 45 сообщенях
Kilatif пока неопределено
По умолчанию C#, сокеты, l2phx

Пишу программку на C#, что то типа ООГ бота. Подобные программы я уже писал на Delphi и Qt, теперь решил попробовать на C#. Все отлично, но везде свой подход работы с сокетами. И я столкнулся с какой-то достаточно интересной проблемой...

Когда отправляю на сервер пакеты больше 256 байт, сервер его благополучно принимает, а вот следующие за ним уже нет. И происходит это, когда я отсылаю пакеты больше 256 байт и только тогда.
Конкретный пример:

Подключаюсь я к GS и сразу отправляю ProtocolVersion размером 267 байт (ему впринципе и 7 хватает, но клиент посылает еще какую-то дрянь вконце и поэтому посылаю ее и я).
После этого клиент мне присылает KeyInit.
Я инициализирую свой Xor и отправляю ему RequestAuthLogin иии... и все. В ответ тишина.

В логах анализатора трафика (Wireshark) этот пакет на сервер видно что отправляется.
Сразу возникает логичная догадка о том, что я неправильно сформировал пакет, но не тут то было.
Когда я посылаю ProtocolVersion размером < 256 байт, то тогда сервер мне вполне нормально присылает ответ на RequestAuthLogin.

Для дебага этой проблемы я решил подключить l2phx.
Подключил его с помощью LSP перехвата соединения и начал следить.

Когда посылаю ProtocolVersion 267 байт, то происходит полная херня:
в программе четко и ясно отсылаю 267 байт, а отсылается только 11, что четко видно как в логах l2phx, так и в логах Wireshark.
Следующие за таким пакетом от клиента вообще больше не отсылаются, сколько бы я не пытался, при этом соединение не разрывается, именно я пытаюсь отослать пакет, а он не отправляется на сервер. К тому же, методом тыка получил простую закономерность, что отсылается как раз таки N mod 256 байт.
Если отсылается < 256 байт пакет, то и с l2phx все работает нормально.

Происходит это конкретно в C# и нигде больше, поэтому посчитал какой-то особенностью работы с сокетами о которых я не знаю.
Чтение пакетов я осуществляю в новом потоке в цикле:
Код:
        private void PacketsReader()
        {
            while (isClientConnected)
            {
                byte[] size = new byte[4];

                lock (thisLock)
                {
                    client.Receive(size, 2, SocketFlags.None);
                }
                packetSize = BitConverter.ToInt32(size, 0);
                packetSize -= 2;

                if (packetSize > 0)
                {
                    packet = new byte[packetSize];
                    client.Receive(packet, packetSize, SocketFlags.None);

                    packet = crypter.Decrypt(packet, packetSize);
                    parser.Parse(packet, packetSize);
                }
            }
        }
Как видно из кода, после дешифрации пакет отправляется на парсер, где определяется тип пакета и вызывается соответствующая ф-я для обработки.
Отправка пакета происходит вот так:
Код:
        public void SendPacket(byte[] packet, int packetSize, bool isEncrypt = true)
        {
            byte[] temp = new byte[packetSize];

            Array.Copy(packet, 0, temp, 0, packetSize);
            if (isEncrypt) temp = crypter.Encrypt(temp, packetSize);

            byte[] sendPacket;

            packetSize += 2;
            sendPacket = new byte[packetSize];

            Array.Copy(BitConverter.GetBytes((byte)packetSize), 0, sendPacket, 0, 2);
            Array.Copy(temp, 0, sendPacket, 2, packetSize - 2);

            lock (thisLock)
            {
                client.Send(sendPacket);
            }
        }
Кто знает почему происходит такая ерунда?
P.S. Если что-то тут не указал, спрашивайте - укажу, отвечу.
Kilatif вне форума   Ответить с цитированием
Старый 05.02.2012, 23:31   #2
Местный
 
Аватар для supernewbie
 
Регистрация: 23.09.2009
Сообщений: 1,232
Сказал Спасибо: 119
Имеет 172 спасибок в 134 сообщенях
supernewbie пока неопределено
По умолчанию

у тебя второй байт размера теряется © кэп

Добавлено через 1 минуту
с C# работал сто лет назад и то пять минут, но инфа 95% что тут неправильно
(byte)packetSize, и надо как-нить типо (short)packetSize
__________________
Начало.

Последний раз редактировалось supernewbie, 05.02.2012 в 23:32. Причина: Добавлено сообщение
supernewbie вне форума   Ответить с цитированием
За это сообщение supernewbie нажился спасибкой от:
Старый 05.02.2012, 23:43   #3
Местный
 
Регистрация: 23.02.2009
Сообщений: 319
Сказал Спасибо: 72
Имеет 60 спасибок в 45 сообщенях
Kilatif пока неопределено
По умолчанию

supernewbie, мда уж... как обычно, идиотские ошибки основанные на идиотских мелочах. И че эт меня переклинило что размер пакета в одном байте храниться? Я уж думал тут инопланетяне замешаны в этих ошибках Спс большое )

Последний раз редактировалось Kilatif, 05.02.2012 в 23:46.
Kilatif вне форума   Ответить с цитированием
Старый 06.02.2012, 10:50   #4
Admin!
 
Аватар для xkor
 
Регистрация: 04.08.2007
Сообщений: 2,360
Сказал Спасибо: 113
Имеет 1,566 спасибок в 651 сообщенях
xkor на пути к лучшему
По умолчанию

Kilatif, интересно твои боты на других языках фрагментацию игровых пакетов тоже не учитывали? при малых размерах пакетов client.Receive будет читать весь пакет, но вот пакеты большего размера из за потоковой сути TCP будут разбиваться на порции и в момент вызова client.Receive могут быть ещё не полностью приняты компом, и client.Receive при этом считает только то количество которое было уже принято, эта функция не ждёт пока в буфере окажется столько байт сколько ты указал считать, считывается столько сколько пришло.
Я в аналоге пакетхака который пишу на шарпе с TCP соединением работаю как с потоком и в асинхронном режиме:
cpp Код:
public abstract class AbstractIOLayer     {         public Action onClose;         public Action<BinaryReader, int> onData;         protected ProxyConnection owner;         public AbstractIOLayer(ProxyConnection owner) { this.owner = owner; }         public abstract void SendData(byte&#91;] buf, int offset, int len);         public abstract void Close();         public abstract bool Actived { get; }         public abstract void BeginRead();     }     public class StreamContainer : AbstractIOLayer     {         private Stream _stream;         private const int _bufSize = 30000;         private readonly byte&#91;] _buf = new byte[_bufSize];         private BinaryReader _reader;         private bool _needRead; // true if need call BeginReceive in OnRecieve         private bool _opened = true;         public override bool Actived { get { return _opened; } }         public StreamContainer(Stream stream, ProxyConnection owner) : base(owner)         {             _reader = new BinaryReader(new MemoryStream(_buf));             _stream = stream;         }         public override void SendData(byte&#91;] buf, int offset, int len)         {             if (_opened) _stream.Write(buf, offset, len);         }         public override void Close()         {             if (_opened)             {                 _opened = false;                 _stream.Close();                 if (onClose != null) onClose();             }         }         public override void BeginRead()         {             _needRead = false; // if call in any layer don't call in OnRecieve             if (_opened) _stream.BeginRead(_buf, 0, _bufSize, OnRead, null);         }         private void OnRead(IAsyncResult r)         {             if (_opened) try             {                 _needRead = true;                 _reader.BaseStream.Position = 0;                 var l = 0;                 try { l = _stream.EndRead(r); }                 //catch (Exception e) { CoreLog.AddExpectedError(e, owner.GetNameWithDir(this)); }                 catch { Close(); return; }                 if (l > 0 && onData != null)                 {                     onData(_reader, l);                     if (_needRead) BeginRead();                 }                 else Close();             }             catch (Exception e) { CoreLog.AddError(e, owner.GetNameWithDir(this)); }         }     }
ЗЫ блин, когда же я пофикшу замену в подсветке синтаксиса символа "[" на "&#91 ;"...
__________________
Я здесь практически не появляюсь!, Skype - ikskor

Последний раз редактировалось xkor, 06.02.2012 в 10:56.
xkor вне форума   Ответить с цитированием
Старый 06.02.2012, 12:31   #5
Местный
 
Регистрация: 10.08.2010
Сообщений: 634
Сказал Спасибо: 22
Имеет 95 спасибок в 70 сообщенях
mira пока неопределено
По умолчанию

Как не странно в "определенных условиях". (Хз зависит от настроек винды соединения или еще чего) сокет не дробит пакеты вообще. И на конкретной машине недочет может быть невиден.
__________________
читернуть бы ништяг
mira вне форума   Ответить с цитированием
Старый 06.02.2012, 14:16   #6
Местный
 
Регистрация: 23.02.2009
Сообщений: 319
Сказал Спасибо: 72
Имеет 60 спасибок в 45 сообщенях
Kilatif пока неопределено
По умолчанию

xkor, на других языках все было вполне нормально и никогда с этим проблем не возникало, хотя я задумывался над этим вопросом и у меня действительно никогда пакеты не дробились. Возможно это один из случаев, которые указал mira.
Kilatif вне форума   Ответить с цитированием
Ответ

  CoderX :: Forums > Основные форумы > Программинг



Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +4, время: 23:45.

vBulletin style designed by MSC Team.
Powered by vBulletin® Version 3.6.11
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Locations of visitors to this page
Rambler's Top100

Вы хотите чувствовать себя в безопасности? чоп Белган обеспечит её!