Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# .NET
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.83/6: Рейтинг темы: голосов - 6, средняя оценка - 4.83
Zippocat
8 / 8 / 5
Регистрация: 11.03.2013
Сообщений: 40
1

Не обрабатываются пакеты Socket

20.08.2013, 21:51. Просмотров 1186. Ответов 16
Метки нет (Все метки)

Пишу серверно клиентскую игру. В которой игрок бегает по полю и ставит бомбы. Загрузка поля с сервера и передвижение игроков работает отлично. А вот установка бомб немного косячит. Через раз, иногда тол ли не обрабатываются толе не доходят пакеты.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
void Server_Start(object obj)
{
    FieldFill(84);
    Player.Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    IPEndPoint IPEndPoint = new IPEndPoint(SInfo.IPAddress, SInfo.Port);
    Player.Socket.Bind(IPEndPoint);
    Player.Socket.Listen(15);
    while (true)
    {
        Socket Client = Player.Socket.Accept();
        Server_Listener(Client);
    }
}
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void Server_Listener(Socket Client)//Прослушка нового подключения
{
    Thread Thread = new Thread(delegate()
    {
        while (true)
        {
            byte[] Buffer = new byte[20480];
            int len = Client.Receive(Buffer);
            string Messenger = DeSerialize(Buffer, len) as string;
            if (Messenger.Contains("PlayerConnect"))
            {
                //Здесь я собираю и передаю поле новому игроку
            }
            if (Messenger.Contains("PlayerMove"))
            {
                //Изменение позиции игроков
            }
            if (Messenger.Contains("BombPlase"))
            {
                //Установка бомб
            }
        }
    });
    Thread.IsBackground = true;
    Thread.Start();
}
Вроде бы все просто но иногда во время движения бомбы не ставятся, у меня подозрение что пакеты на установку бомб просто перебиваются пакетами на движение.
0
Миниатюры
Не обрабатываются пакеты Socket  
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.08.2013, 21:51
Ответы с готовыми решениями:

Не обрабатываются исходники .NET Framework Full SDK
Качнул .NET Framework Full SDK . Запускаю и получаю следующее: на aspx...

Перехватить пакеты
Добрый день. Подскажите пожалуйста каким ПО можно перехватить пакеты, которое...

Не устанавливаются пакеты NuGet
Не удалось загрузить индекс службы для источника...

Рваные пакеты с com порта, DataRecieved
Здравствуйте прошу помочь. Проблема заключается в следующем. Есть устройство...

Wireshark, как разобрать пакеты?
подскажите по поводу протокола MRIM. пишу клиент для mail.ru как с помощью...

16
MegaSinner
98 / 94 / 9
Регистрация: 09.04.2010
Сообщений: 746
20.08.2013, 22:17 2
Цитата Сообщение от Zippocat Посмотреть сообщение
просто перебиваются пакетами на движение.
а что мешает юзать один сокет для координат, а другой для расстановки бомб?
0
Zippocat
8 / 8 / 5
Регистрация: 11.03.2013
Сообщений: 40
20.08.2013, 22:23  [ТС] 3
Цитата Сообщение от MegaSinner Посмотреть сообщение
а что мешает юзать один сокет для координат, а другой для расстановки бомб?
А как в обычных играх делают, там разве на каждый новый функционал идет новый сокет?
0
MegaSinner
98 / 94 / 9
Регистрация: 09.04.2010
Сообщений: 746
20.08.2013, 22:33 4
Цитата Сообщение от Zippocat Посмотреть сообщение
А как в обычных играх делают, там разве на каждый новый функционал идет новый сокет?
Хм, самом интересно стало)
Я так понимаю надо сформировать такой пакет "X:Y:1 или 0 (бомба есть или нету)"
0
onicdr
37 / 36 / 7
Регистрация: 01.08.2013
Сообщений: 106
21.08.2013, 11:12 5
Возможно просто пакеты вперемешку идут и конец одного принятого пакета не соответствует действительному концу команды \ действия. Проверка есть на конец принятого пакета? Поясню: посылается "...X:10:Y11:BOMB:1;X:11:Y11:BOMB:1" (к примеру), пакеты могут прийти:
"...X:10:Y11:BO" и потом "MB:1;X:11:Y11:BOMB:1" => потеря бомбы на x10:y11 (если не учитывается такое).
0
Zippocat
8 / 8 / 5
Регистрация: 11.03.2013
Сообщений: 40
21.08.2013, 15:14  [ТС] 6
Цитата Сообщение от onicdr Посмотреть сообщение
Возможно просто пакеты вперемешку идут и конец одного принятого пакета не соответствует действительному концу команды \ действия. Проверка есть на конец принятого пакета? Поясню: посылается "...X:10:Y11:BOMB:1;X:11:Y11:BOMB:1" (к примеру), пакеты могут прийти:
"...X:10:Y11:BO" и потом "MB:1;X:11:Y11:BOMB:1" => потеря бомбы на x10:y11 (если не учитывается такое).
Похоже что так и есть, пакеты движения идут вместе с пакетами установки бомбы. Но как тогда в таком случае их отсеять? Вродебы я правильно принимаю пакты, или я что то упустил?
C#
1
2
3
byte[] Buffer = new byte[6000];
int len = Client.Receive(Buffer);
string Messenger = Encoding.UTF8.GetString(Buffer, 0, len);
0
Миниатюры
Не обрабатываются пакеты Socket  
onicdr
37 / 36 / 7
Регистрация: 01.08.2013
Сообщений: 106
21.08.2013, 15:53 7
Сделано всё верно, просто принцип передачи таков, "пакетами". Тут уж либо второй порт открывать, либо придумывать, как отделять битую информацию от целой и "шаги" от "действий".

Добавлено через 3 минуты
Хотя... лучше на стороне передачи сделать иначе - пока не отослан пакет, не пытаться слать второй.
0
Убежденный
Ушел с форума
Эксперт С++
16126 / 7273 / 1181
Регистрация: 02.05.2013
Сообщений: 11,637
Записей в блоге: 1
Завершенные тесты: 1
21.08.2013, 16:01 8
Ребята, ну какие еще пакеты на уровне TCP ?
TCP - это просто поток байт. И этот протокол гарантирует правильный
порядок доставки данных. Отправили "ABC", получили "ABC". Возможно,
"A", затем "BC". Или "AB", затем "C". Но никак не "ACB" или "BAC".

Цитата Сообщение от Zippocat Посмотреть сообщение
int len = Client.Receive(Buffer);
string Messenger = DeSerialize(Buffer, len) as string;
if (Messenger.Contains("PlayerConnect"))
{
//Здесь я собираю и передаю поле новому игроку
}
if (Messenger.Contains("PlayerMove"))
{
//Изменение позиции игроков
}
if (Messenger.Contains("BombPlase"))
{
//Установка бомб
}
Принципиально неверный кусок кода.
Никто не гарантирует, что "PlayerMove" или "PlayerConnect" придут в
одной порции, которую примет метод Receive. С TCP нужно работать как с
потоком байт, поделенным на куски заранее неизвестного размера.
Только так и никак иначе. Вот когда перепишете как подобает, никаких
"пакетов" у вас теряться не будет.
0
Zippocat
8 / 8 / 5
Регистрация: 11.03.2013
Сообщений: 40
21.08.2013, 16:13  [ТС] 9
Я не знаю как подобает, я надеялся что тут подскажут Те примеры что я рассматривал на парах были сильно поверхностны и просты.
Часто сообщения идут вместе, я решил в конец каждого сообщения дописывать символ '%' и уже потом при получение разбивать их отдельные части.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
byte[] Buffer = new byte[6000];
int len = Client.Receive(Buffer);
string[] Messenger = ByteToString(Buffer, len).Split('%');
for (int i = 0; i < Messenger.Length; i++)
{
    if (Messenger[i].Contains("PlayerConnect"))
    {
        //...
    }
    if (Messenger[i].Contains("PlayerMove"))
    {
        //...
    }
    if (Messenger[i].Contains("BombPlase"))
    {
        //...
    }
}
0
Убежденный
Ушел с форума
Эксперт С++
16126 / 7273 / 1181
Регистрация: 02.05.2013
Сообщений: 11,637
Записей в блоге: 1
Завершенные тесты: 1
21.08.2013, 16:23 10
Этот код не учитывает ситуацию, когда приходит, например, такая строка:
"PlayerConnect%Bom", а затем "bPlase" (в два вызова Receive).
Из-за этого данные и теряются.
0
Anklav
442 / 301 / 46
Регистрация: 23.01.2013
Сообщений: 640
Завершенные тесты: 2
21.08.2013, 18:16 11
Может проще в начале сообщения писать его длину?

1. Сохранить полученные данные в MemoryStream.
2. Когда получено полное сообщение (возможно с началом следующего):
а)извлекаем данные из MemoryStream, полученное сообщение + остаток.
б)полученное сообщение отдаем на обработку.
в)MemoryStream освобождаем.
г)создаем новый MemoryStream с остатком(если есть)
3. Продолжаем принимать сообщение.

Как проверить получено сообщение или нет?
Если в MemoryStream записано меньше четырех байт (sizeof(int)) продолжаем принимать сообщение, ведь минимальная длинна его 4 байта.
Если в MemoryStream записано больше 4 байт, то конвертируем первые 4 байта в int и сравниваем полученное число с длинной MemoryStream, если полученная длинна меньше того что у нас записано в потоке, значит сообщение получено, и можно извлекать данные (главное не потерять остаток!)
0
Fuilie
6 / 6 / 3
Регистрация: 11.02.2013
Сообщений: 34
21.08.2013, 19:53 12
Так на самом деле и делают. Формат посылки такой: длинна 4 байта в int, остальное данные. В начале поля данных добавляем байт для определения типа посылки(что бы знать как обрабатывать)

P.S. Ну самый простой способ: передавать сообщения ввиде объектов используя серелизацию.
0
Убежденный
Ушел с форума
Эксперт С++
16126 / 7273 / 1181
Регистрация: 02.05.2013
Сообщений: 11,637
Записей в блоге: 1
Завершенные тесты: 1
21.08.2013, 19:59 13
Цитата Сообщение от Anklav Посмотреть сообщение
Может проще в начале сообщения писать его длину?
Можно. Это одна из типовых схем.
Вычитываем данные, пока не наберется на "sizeof (int)" байт, узнаем длину.
Например, она равна 100 байтам. Дальше вызываем Receive с размером буфера 100 байт.
Прочитали, скажем, 75, читаем еще 25, и т.д. Ну а после работаем с цельным сообщением.
Хотя для сообщений небольшого размера это не самый эффективный способ, ведь
здесь естественная длина TCP-сегментов будет искусственно "обрезаться".
0
Anklav
21.08.2013, 22:48
  #14

Не по теме:

Fuilie, Убежденный, :D Я в курсе, это был вопрос-предложение, направленное ТС

0
Убежденный
Ушел с форума
Эксперт С++
16126 / 7273 / 1181
Регистрация: 02.05.2013
Сообщений: 11,637
Записей в блоге: 1
Завершенные тесты: 1
21.08.2013, 22:50 15
Anklav, прошу прощения
По какой-то непонятной для меня причине принял Вас за топикстартера.
Сообщение адресовано ему.
0
Zippocat
8 / 8 / 5
Регистрация: 11.03.2013
Сообщений: 40
21.08.2013, 23:18  [ТС] 16
А что если просто помечать сообщения символом начала, например '#' и символом конца '%'. Зачем столько мороки с байтами?
0
Anklav
442 / 301 / 46
Регистрация: 23.01.2013
Сообщений: 640
Завершенные тесты: 2
22.08.2013, 00:06 17
Это позволяет сериализовать объекты и отправлять их пакетами, при получении десериализовать. Что очень удобно.

Конечно при этом размер пакета увеличивается.

Да и не морока это вовсе... парсить строки вот это морока.
0
22.08.2013, 00:06
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
22.08.2013, 00:06

COM-порт принимает не все пакеты
И так, у меня есть программа которая работает с com-портом. Но проблема в том,...

Как снифать пакеты, отправленные HttpClient
Собственно, вопрос в теме. С помощью Charles смотрел пакеты, посылаемые...

Перенаправить пакеты на прокси сервер программно
Всем привет. Известно, что некоторая программа отправляет пакеты на адрес...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru