Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > разработка игр, графический дизайн и моделирование > Gamedev - cоздание игр: Unity, OpenGL, DirectX
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 01.12.2010, 15:24   #1
Asker13
Форумчанин
 
Аватар для Asker13
 
Регистрация: 01.12.2010
Сообщений: 140
По умолчанию Разработка сетевых приложений

Здравствуйте. Я знаю основы работы с ClientSocket и ServerSocket. У меня есть некоторые вопросы.
1) Начнём с простого. Я не понимаю, как передавать значение какой-либо переменной клиенту. Скажем, можно конечно переделывать цифры в строку (IntToStr), затем передавать строку посредством SendText и уже расшифровывать данные на сервере, но я уверен, что этот способ неправильный и существует другой, изобретать велосипед не нужно.

2) Допустим каждые 50 мс клиент серверу отправляет какой-либо набор переменных. Допустим две переменные x и y. Предположим, что в программе имеется поле для отправки произвольных сообщений. Клиент напечатал сообщение, данные должны отправиться на сервер. Но как серверу определить, какие данные к нему поступили: раннее упомянутый набор переменных или текст? Мой вариант - это отсылка ещё двух дополнительных переменных, значения которые укажут, что читать. Допустим эти две переменные будут a и b типа byte. Если a = 1 (а оно всегда будет равно 1), то читать набор переменных, если же b = 1, то значит читать и последующий текст. Разумен ли такой способ? Если нет, есть ли другие?

Большое спасибо за понимание и внимание, прошу помощи, советов.
Asker13 вне форума Ответить с цитированием
Старый 01.12.2010, 15:47   #2
_-Re@l-_
C++, Java
Старожил
 
Аватар для _-Re@l-_
 
Регистрация: 10.04.2010
Сообщений: 2,665
По умолчанию

Цитата:
Здравствуйте. Я знаю основы работы с ClientSocket и ServerSocket. У меня есть некоторые вопросы.
1) Начнём с простого. Я не понимаю, как передавать значение какой-либо переменной клиенту. Скажем, можно конечно переделывать цифры в строку (IntToStr), затем передавать строку посредством SendText и уже расшифровывать данные на сервере, но я уверен, что этот способ неправильный и существует другой, изобретать велосипед не нужно.
А почему бы и нет?Не такой уж и плохой способ. Никакого велосипеда здесь нет.
_-Re@l-_ вне форума Ответить с цитированием
Старый 01.12.2010, 22:40   #3
Daemonghost
Пользователь
 
Аватар для Daemonghost
 
Регистрация: 25.11.2010
Сообщений: 46
По умолчанию

пишу игрушку на сокетах.
пользуюсь анализом символов
пример: id:35pX:342pY:456
на сервере анализирую строку.

Код:

if (st[k]='i') and (st[k+1]='d') and (st[k+2]=':') then
begin
    for n:=k+3 to length(st) do
       begin
       str:=str+st[n];
       if (st[n+1]='p') and (st[n+2]='X') and (st[n+3]=':') then
                   begin
                   id:=strtoint(str);
                   for m:=n+4 to length(st) do
                          begin
                            str1:=str1+st[m];
       if (st[m+1]='p') and (st[m+2]='Y') and (st[m+3]=':') then
                   begin
                  posX:=strtoint(str1);
                   for r:=m+4 to length(st) do
                      str2:=str2+st[r];
                     posY:=strtoint(str2);
Может есть другой способ, тоже очень интересно.

Последний раз редактировалось Daemonghost; 01.12.2010 в 22:49.
Daemonghost вне форума Ответить с цитированием
Старый 02.12.2010, 06:41   #4
Blade
Software Engineer
Участник клуба
 
Аватар для Blade
 
Регистрация: 07.04.2007
Сообщений: 1,618
По умолчанию

Цитата:
Сообщение от Daemonghost Посмотреть сообщение
пишу игрушку на сокетах.
пользуюсь анализом символов
пример: id:35pX:342pY:456
на сервере анализирую строку.

Код:

if (st[k]='i') and (st[k+1]='d') and (st[k+2]=':') then
begin
    for n:=k+3 to length(st) do
       begin
       str:=str+st[n];
       if (st[n+1]='p') and (st[n+2]='X') and (st[n+3]=':') then
                   begin
                   id:=strtoint(str);
                   for m:=n+4 to length(st) do
                          begin
                            str1:=str1+st[m];
       if (st[m+1]='p') and (st[m+2]='Y') and (st[m+3]=':') then
                   begin
                  posX:=strtoint(str1);
                   for r:=m+4 to length(st) do
                      str2:=str2+st[r];
                     posY:=strtoint(str2);
Может есть другой способ, тоже очень интересно.
Ужас, товарищи
Читайте про регулярные выражения (не знаю, правда, как с ними обстоят дела в делфи, но уверен что они там тоже есть, в каком либо виде)
Мужество есть лишь у тех, кто ощутил сердцем страх, кто смотрит в пропасть, но смотрит с гордостью в глазах. (с) Ария
Blade вне форума Ответить с цитированием
Старый 02.12.2010, 10:26   #5
Asker13
Форумчанин
 
Аватар для Asker13
 
Регистрация: 01.12.2010
Сообщений: 140
По умолчанию

Цитата:
id:35pX:342pY:456
Если у вас чтение идёт по порядку, то лучше наверное обойтись только цифрами. Скажем переделать вашу исходную строку в
Цитата:
35 342 456
Читать цифру до пробела, запоминать эту цифру, переделывать из строки в число, затем всё снова повторяется, пока не дойдёте до конца строки.
Цитата:
Читайте про регулярные выражения
Спасибо за совет.
Цитата:
А почему бы и нет?Не такой уж и плохой способ. Никакого велосипеда здесь нет.
Я находил информацию о буфере, который отсылается от клиента серверу, но там не объяснялось на конкретном примере, как из этого буфера достать нужные данные и присвоить опр. переменным полученные значения. Но было ясно, что с помозью буфера пересылается информация не строковая, а числовая, поэтому я посудил, что в строку не стоит переделывать числа.
Asker13 вне форума Ответить с цитированием
Старый 02.12.2010, 16:01   #6
Beermonza
Инженер ИС
Старожил
 
Аватар для Beermonza
 
Регистрация: 13.12.2006
Сообщений: 2,671
По умолчанию

Ничего не нужно отделять пробелами и переделывать строки в символы, ...достаточно воспользоваться байтовым массивом. Одна ячейка массива - одна цифра от 0 до 255. Ваша запись id:35pX:342pY:456 или 35 342 456 (17 байт и 10 байт) будет весить 4 байта:

Код:
Mas[0] := 1; // код команды
Mas[1] := 35; // ID
Mas[2] := 200; // Х
Mas[3] := 250; // Y

{имя компонента}.Socket.SendBuf(Mas, 4);
Да, значения по-X и по-Y ограничены в 255, а оно нужно больше? ...если клетка карты скажем 50х50 пикселов, то вы покрываете уже 12750 пикселов. Задача сводится к передачи координат в масштабе клеток карты, а смещение по пикселам уже доводит отдельная переменная, я это отмечал в теме "Уроки по созданию игр для новичков". Если нужны большие значения, то нет ничего проще представить число двумя байтами, тремя, четырьмя (если такие космические числа есть вообще в игре).

Последовательность считывания заложена в коде команды, в 0-й ячейке. Т.е. через case берется Mas[0] и в зависимости от значения выполняется определенная обработка команды, включая последовательность, составные и упакованные данный. Следует обратить внимание на то, что если у вас в одной команде могут быть как однобайтовые так и двухбайтовые числа, то нужно представлять их все двухбайтовой последовательностью: 0 200 = 200, 1 135 = 390 (1 * 255 + 135) и т.д.
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его
Beermonza вне форума Ответить с цитированием
Старый 02.12.2010, 16:24   #7
Asker13
Форумчанин
 
Аватар для Asker13
 
Регистрация: 01.12.2010
Сообщений: 140
По умолчанию

Beermonza, большое спасибо за помощь. Вы всё очень понятно и доступно объяснили.
Asker13 вне форума Ответить с цитированием
Старый 02.12.2010, 16:59   #8
Beermonza
Инженер ИС
Старожил
 
Аватар для Beermonza
 
Регистрация: 13.12.2006
Сообщений: 2,671
По умолчанию

Asker13, если понадобится передать отрицательные целые числа, десятичные, тот же текст, это все выполняется в виде последовательности байт, ведь информация любого типа в машинном представлении это, суть, последовательность байт, сетевой поток не исключение.
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его
Beermonza вне форума Ответить с цитированием
Старый 02.12.2010, 20:21   #9
Daemonghost
Пользователь
 
Аватар для Daemonghost
 
Регистрация: 25.11.2010
Сообщений: 46
По умолчанию

Цитата:
Сообщение от Beermonza Посмотреть сообщение

Код:
Mas[0] := 1; // код команды
Mas[1] := 35; // ID
Mas[2] := 200; // Х
Mas[3] := 250; // Y

{имя компонента}.Socket.SendBuf(Mas, 4);
а можно более подробно расписать, про сам массив и про процедуру его отправки и приемки.

так же интересует цифра 4, что она обозначает.

пытался принять через:

Код:
ClientSocket1Read(Sender: TObject;
  Socket: TCustomWinSocket);
var mas:array[0..3] of byte;
begin
Socket.ReceiveBuf(mas,4);

if mas[0] = 1 then
  begin
  id:=mas[1];
  position_x:=mas[2];
  position_y:=mas[3];
  end;
....
не вышло, после каждой второй компиляции пара клиент-сервер вешала комп до состояния хард резета.
Может я что-то не так делаю?

ps. с цифрой 4 разобрался.

Последний раз редактировалось Daemonghost; 03.12.2010 в 00:43.
Daemonghost вне форума Ответить с цитированием
Старый 03.12.2010, 01:04   #10
Beermonza
Инженер ИС
Старожил
 
Аватар для Beermonza
 
Регистрация: 13.12.2006
Сообщений: 2,671
По умолчанию

Я привел пример заполнения и отправки пакета. SendBuf(Mas, 4) - это стандартная команда сокета на отправку. Если поднести курсор к ней, то можно увидеть что она требует на входе. А именно вот это:

Код:
function TCustomWinSocket.SendBuf(var Buf; Count: Integer): Integer;
...где, Buf - это массив некоторого типа, Count - длина данных в байтах.
Стало быть команда SendBuf(Mas, 4) отошлет пакет длинной 4 байта (array[0..3] of byte).

Принимать такой пакет нужно уже после того как соединение устаканилось, иначе можно зацепить переписку сокетов во время установки связи. Т.е. нужна пауза от подключения до начала работы с сокетами, ...ну а раз уж эта тема посвящена сетевым приложениям, то в целях обеспечения безопасности и надежности, первым "диалог" должен начинать сервер, ...как бы говоря, после готовности и создания канла: "кто ты такой, назови свое имя", ...клиент должен ответить некоторым пакетом (если клиент начал "болтать" первым, то его нужно отключить).
Вот, к примеру, то, что показал выше это ответ клиента. Он прислал данные. Теперь их нужно принять на стороне сервера, используя специальное определение длины пакета, вот так:

Код:
  BufLength := Socket.ReceiveLength;
  Socket.ReceiveBuf(Mas, BufLength);
Далее можно вытягивать из массива данные. Примените точку останова. В окне листинга, после компиляции, слева проставляются синие кружки - это обработанные строки. Если нажать на такой кружок, он станет красным, и вся строчка подсветится красным. Нужно запустить приложение, и когда программа дойдет до точки останова, она войдет в паузу. Нажимая F8 можно в ручном режиме переходить по строчкам. На какой строке возникнет ошибка, там и проблемы в коде. Нужно поставить точку останова вначале процедуры OnRead. Запустить соединение и после отправки пакета с сервера смотреть построчно что происходит, ...можно наводить курсор на код и смотреть текущие значения переменных.
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его
Beermonza вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Разработка приложений для Windows Mobile 6.1 AlexBonel Windows 4 08.10.2009 17:44
Разработка приложений под Windows Mobile 6.1 AlexBonel Помощь студентам 0 05.10.2009 10:40
C++ взаимодействие с АЦП/ЦАП и разработка сетевых приложений iukash Свободное общение 4 14.08.2009 18:02
Создание сетевых приложений в delphi martinenko Работа с сетью в Delphi 6 09.05.2009 20:23