Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

ServerSocket

55K
23 января 2011 года
Frio
25 / / 26.08.2010
Доброго времени суток. Есть 2 вопроса.
1) Как лучше передавать данные через интернет , через создания сокетов с помощью WINAPI или через ServerSocket самого билдера ? Какие у кого преимущества ?
2) Если мне нужно передавать разные данные. Например координату и тип объекта с этой координатой, как это реализовать? Спасибо.
11
23 января 2011 года
oxotnik333
2.9K / / 03.08.2007
Цитата: Frio
Доброго времени суток. Есть 2 вопроса.
1) Как лучше передавать данные через интернет , через создания сокетов с помощью WINAPI или через ServerSocket самого билдера ? Какие у кого преимущества ?
2) Если мне нужно передавать разные данные. Например координату и тип объекта с этой координатой, как это реализовать? Спасибо.


1. Монопенисуально
2. Структурой типа

 
Код:
struct
{
    int X;
    int Y;
    int Type;
}

ну и соответственно на сервере и на клиенте Type должен быть одинаково описан.
278
23 января 2011 года
Alexander92
1.1K / / 04.08.2008
Все зависит, какое приложение вы пишете. Если у вас чистое Win32-приложение, лучше используйте WinAPI. Если пишете GUI-приложение с формами - тогда для единства стиля уже используйте TServerSocket. По поводу преимуществ: билдеровский компонент, безусловно, скрывает часть кода, который вам придется писать, используя WinAPI. В то же время, имейте в виду, что любой компонент - это "черный ящик", в то время как свой код вы всегда знаете. Возможно, можно учесть здесь проблему переносимости: если есть вероятность, что когда-либо ваш проект нужно будет компилировать не в билдере, а в другой среде - используйте кроссплатформенное средство, т.е. WinAPI.

Теперь касательно второго вопроса, как передавать данные. По большому счету, вам нужно разработать собственный протокол передачи данных (либо воспользоваться одним из существующим, но если вы спрашиваете о реализации - то я называю наиболее общий вариант). Посмотрите структуру некоторых существующих протоколов уровня приложения. Обычно передача данных осуществляется на уровне пакетов, который содержит тип пакета, длину передаваемых данных и собственно данные (это называется TLV-структурой - "Type, Length, Value").
55K
23 января 2011 года
Frio
25 / / 26.08.2010
oxotnik333 можно было не так грубо.
Alexander92 - у меня уже была одна программа но там передавались только координаты. Передавал весь массив координат целиком, потомучто при передаче через цикл пакеты склеивались и получалась неразбериха. Я так понял чтобы клиент различал данные нужно вводить в покет с данными какието "разделители" ? Но как их потом прочесть , ведь весь массив в строку не пихнёшь для нахождения того "разделителя" . И ещё, есть ли разница в скорости передачи между написанным сокетом от руки и билдеровским ServerSocket'ом ?
278
23 января 2011 года
Alexander92
1.1K / / 04.08.2008
Не совсем понял, что вы имеете в виду, но алгоритм приема должен выглядеть следующим образом
1. Сервер видит, что сокет не пустой.
2. Сервер читает заранее предопределенное количество байт заголовка, извлекает из него длину тела пакета.
3. Сервер читает тело пакета в соответствии с той длиной, которую он извлек на прыдыдущем шаге.

Само тело может быть тоже "многоступенчатым", т.е. в него могут быть вложены подпакеты. Почитайте, например, про структуру PCM WAVE-файла, про структуру TCP-фрейма, про передачу данных в HTTP POST-запросе, ну или про FLAP'ы в протоколе ICQ, на худой конец. :)


Цитата:

И ещё, есть ли разница в скорости передачи между написанным сокетом от руки и билдеровским ServerSocket'ом


Затрудняюсь ответить, очень мало работал с билдером. Скажу одно: безусловно, любая обертка всегда работает немного медленнее, чем оригинал. Но разница по скорости между "родным" сокетом и компонентами играет значительную роль только если этот вопрос ОЧЕНЬ принципиальный. В бытовых приложениях скорости компонентов обычно вполне достаточно.

55K
23 января 2011 года
Frio
25 / / 26.08.2010
К примеру такой случай. Каждые 40мс передаются какието координаты независимо ни от чего. И мне вдруг понадобилось отправить ещё какуюто переменную. Как это осуществиться ? Извините я с сокетами и интернетом очень мало работал.
5
23 января 2011 года
hardcase
4.5K / / 09.08.2005
Цитата: Frio
Каждые 40мс передаются какието координаты независимо ни от чего.

Такой точности добиться в условиях Windows и TCP/IP сетей невозможно.

278
23 января 2011 года
Alexander92
1.1K / / 04.08.2008
Вы должны строго типизировать все пакеты, которые вы отправляете. Например:
 
Код:
#define PACKET_COORDINATS   1
#define PACKET_SOME_VAR     2


Далее, вы определяете структуру самого пакета, например:
 
Код:
typedef struct tagPacket {
  BYTE Type;
  UINT Length;
  BYTE Data[32767];
} PACKET, *LPPACKET;


Теперь примеры отправки данных. Для отправки координат вы строго оговариваете, что каждая координата занимает, например, два байта. Тогда имеете:
Код:
int SendPacket(SOCKET *s, PACKET *p) {
  int ret = 0;
  // преобразовать p->Type к строковой переменной TypeStr
  // преобразовать p->Length к строковой переменной LengthStr
  ret = send(s, TypeStr, sizeof(p->Type), 0);
  ret += send(s, LengthStr, sizeof(p->Length), 0);
  ret += send(s, (CHAR *)&(p->Value), p->Length, 0);
  return ret;
}

SOCKET s;
// здесь создаете сокет, открываете соединение
PACKET packet;
BYTE X[2], Y[2]; // предполагается, что вы уже преобразовали свои координаты в массив байт
// обнулить пакет
ZeroMemory((LPVOID)&packet, sizeof(PACKET));
packet.Type = PACKET_COORDINATES;
packet.Length = 4; // 2 координаты
CopyMemory((LPVOID)&Value[0], (LPVOID)X, 2);
CopyMemory((LPVOID)&Value[2], (LPVOID)Y, 2);
// отправка
SendPacket(&S, &packet);

// а теперь вам нужно отправить еще какую-то переменную Z:
DWORD Z; // например, она типа DWORD
ZeroMemory((LPVOID)&packet, sizeof(PACKET));
packet.Type = PACKET_SOME_VAR;
packet.Length = sizeof(DWORD); // размер вашей переменной
CopyMemory((LPVOID)&Value[0], (LPVOID)&Z, sizeof(DWORD));
// отправляете
SendPacket(&S, &packet);

// закрываете сокет


Соответственно, на стороне сервера обработка следующая:
Код:
SOCKET S;
// открываете сокет, принимаете соединение

// прочесть один байт - тип пакета
SHORT type;
recv(S, (CHAR *)&type, 1, 0);

// прочесть четыре байта - длина пакета
CHAR len[5] = {'\0'};
recv(S, len, 4, 0);

BYTE X[2], Y[2];

// определить дальнейшие операции в соответствии с тем, какой пакет вы получили:
switch(type) {
  case PACKET_COORDINATES:
    // получить X
    recv(S, (CHAR *)X, 2, 0);
    // получить Y
    recv(S, (CHAR *)Y, 2, 0);
   // ...
  case PACKET_SOME_VAR:
   // обработать вашу переменную
}


Плюс, разумеется, обработка ошибок и т.п. Заранее прошу прощения, если где-то ошибся, писал сходу, но идею, думаю, поняли.
55K
23 января 2011 года
Frio
25 / / 26.08.2010
Да, спасибо огромное..Чтото подобное я себе представлял просто не мог самомстоятельно написать...Спасибо
278
23 января 2011 года
Alexander92
1.1K / / 04.08.2008
Почитайте еще про структуру TLV-пакетов, у вас отпадут многие вопросы.
20K
27 января 2011 года
Vlad_Imir
14 / / 16.03.2007
Тут еще один момент надо учитывать, если пересылаете структурированные данные.
При компиляции серверной и клиентской части на разных компиляторах (скажем клиент на линуксе а сервер на виндовс) линкеры могут по разному выравнивать структуры на клиентской и серверной стороне. То есть, если у вас в сумме набирается размер 15 байт, он может выравнять до 16 в одном случае и до 64 на другом, или оставить как есть.

Можно использовать следующий прием:

 
Код:
#pragma pack (push)
#pragma pack(1) // здесь выравнивается до байта
struct info {
   // ваши данные
   // ...
};
#pragma pack (pop)
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог