Спортивный сокетный интерес

Все, что вы хотели знать о программизме, но боялись спросить.
vg
Маньяк
Сообщения: 2803
Зарегистрирован: 29 май 2003, 22:29
Откуда: Магадан - Миссиссага

Спортивный сокетный интерес

Сообщение vg »

Недавно обсуждался вопрос – «Как лучше написать «сервисок»?» Автор - Mark. Там я тоже задавал вопрос, на который не получил ответа – «А каким должен быть прикладной протокол, определяющий информационный обмен клиент/серверного приложения, написанного «на сокетах»?».

Только протокол определяет правила обмена данными. Что в протокол заложишь, то в реализации и получишь. И кстати, сокеты здесь не причём. Важный вопрос. Возможно, что Mark решал простые задачи – чтение данных из одной или нескольких (но одних и тех же) таблиц удалённой базы. И говорить нечего - любые средства хороши для построения эффективного и надёжного обмена. Оверхеды – минимальны ;)). Возможно, поэтому Makr так ничего и не ответил.

Вот схожие ситуации, где я бы тоже не отвечал с учётом их тривиальности:
1) читаем и пишем в таблицы, структура которых известна клиенту «заранее». При этом ещё лучше, если MEMO и BLOB – отсутствуют. Скорее всего, и клиента и сервер здесь проектирует один и тот же человек.
2) пишется протокол под «конкретную» задачу. Есть вполне определённая база. Клиент обращается к серверу не с SQL запросами, а с запросами типа – GET_FOLDERS, GET_DEPARTMENTS. Приблизительно так построено приложение «1C Архив» (если я правильно понял, промониторив сетефой трафик). Совершенно классное и эффективное Российское приложение.

Но мне хотелось выяснить: «Каким должен быть протокол, если предполагается решение более сложных задач? Например, клиентские приложения работают по инет с DBMS так, как если б клиенты использовали DCOM в LAN c Windows-машинами. Задают SQL вопросы и получают достаточно быстро достойные SQL ответы».

Я не занимался и не занимаюсь этой задачей всерьёз. Более того, я б отстаивал существующие промышленные решения, а не суррогат. В корпоративной интранет среде – тем более. Даже для корпоративных сетей, разделённых межсетевыми экранами, я сторонник DCOM, для Win, разумеется (здесь «сложности» с фильтрацией пакетов больше надуманны. Хотя маленько есть, конечно).
Так, что мой вопрос и всё, что ниже – из спортивного интереса и желания узнать, как бы такой «сокетный» протокол проектировали многоопытные (не говорю «профи» - Woozy и Marmota боюсь).

Невозможно предметно обсуждать «ничего». Поэтому, в свободное от основной работы время я написал протокол, сервер и клиента. Сделал это для «затравки» обсуждения. Из спортивного интереса. Вот код (работающий), реализующий рассматриваемый «сокетный» протокол для «затравки» обсуждения:

Код: Выделить всё

_DWORD		rc;
_DWORD		hQuery;

if ( FAILED(rc = QueryCreate("MY_DB_ALIAS", &hQuery) ))
	return rc;

if ( FAILED(rc = QueryOpen(hQuery, "select * from tbl1")) )
{
	QueryDelete( hQuery );
	return rc;
}

int		ival;
LPTSTR		sval;

while ((rc = QueryEof( hQuery )) != QUERYEOF_S_EOF)
{
	if ( FAILED( rc = QueryIntegerField( hQuery, "id", &ival) ) ||
	     FAILED( rc = QueryStringField(  hQuery, "txt", &sval) ))
		 break;
	_tprintf(_TEXT("id = %d txt = %s\n"), ival, sval);

	if ( FAILED(rc = QueryNext( hQuery )) )
		break;
}

if ( FAILED( rc ))
	OnErr ( rc );

return QueryDelete( hQuery );
В LAN – работает весьма эффективно. Имеются в виду ощущения пользователя клиентской программы. Для сравнения вот результаты тестирования выполнения того же кода и использованием ODBC и ADO – время выполнения кода, что выше в цикле 100 раз (без _tprintf, разумеется):

1) «На сокетах», с использованием ODBC на сервере ~ 6 сек.
2)Обычное приложение, использующее ODBC и DSN к удалённой базе на том же сервере ~ 5 – 7 сек.
3) Тоже, что и в п.2, но с использованием ADO ~ 1 – 3 сек.

ВНИМАНИЕ ВОПРОС:

Каким должен быть протокол, если это не LAN, а инет?
MarkM
Пользователь
Сообщения: 113
Зарегистрирован: 24 сен 2003, 21:52

Re: Спортивный сокетный интерес

Сообщение MarkM »

vg писал(а):Недавно обсуждался вопрос – «Как лучше написать «сервисок»?» Автор - Mark. Там я тоже задавал вопрос, на который не получил ответа – «А каким должен быть прикладной протокол, определяющий информационный обмен клиент/серверного приложения, написанного «на сокетах»?».

Каким должен быть протокол, если это не LAN, а инет?
1. Протокол может быть ЛЮБОЙ! Все зависит от конкретной задачи.
2. Посмотри внутрь профессионально написаных протоколов апп уровня, типа ФТП, СМТП, итп. КТО ВО ЧТО ГОРАЗД!

Я спрашивал в надежде найти что нибудь наиболее стандартное. Не нашел. Мой сервис работает с сугубо текстовыми данными. Поэтому HTTP подошел бы более всего. Но он "односессионный". Т.е. один запрос/ответ на сессию. Можно сэмулировать многозапросную сессию и на ХТТП, но это излишнее усложнение по сравнению с "голыми" сокетами и "самопальным" протоколом.
И еще почему я хотел готовый протокол, чтобы использовать уже наработанный софт для его реализации. Энжин какой нибудь, типа сервлетного. К сожалению ничего не подошло. :( Апачевский Авалон наиболее близок, но сильно уж сложен для мой задачи. Как из пушки по воробъям.

Короче, я открываю сокет и обмен идет на "словах", тэгах.

Код: Выделить всё

begin session
1. CLIENT:PUPKIN
2.                                  SEVER:OK
3. CLIENT:GETTHING
4.                                  thing
5. CLIENT:OK
end session                           
Примитивно? Меня устраивает. Возможно можно было бы сделать "язык" в бинарном виде. Было бы компактно. Но не удобно в поддержке. Или в XML. Было бы модно. Но более тяжеловесно, парсеры там всякие...
Протокол жесткий. Так задумано. Гибкости никакой нет и не надо пока. Так что что клиент, что сервер валятся в эксепшн при малейшем несоответствии запросов-ответов "стандартному" паттерну. И это правильно.

Рад, если тебе это помогло.
Аватара пользователя
Marmot
Графоман
Сообщения: 38419
Зарегистрирован: 17 фев 2003, 17:58
Откуда: Canyon Heights
Контактная информация:

Сообщение Marmot »

А вот у меня нету едиственного ответа на это вопрос.
Я на жизнь зарабатываю как System Architect и, из своего опыта знаю, что это зависит от очень большого количества факторов.
В каждом случае надо конкретно разбираться, чего люди хотят, знают, умееют, на чём будет бегать, и т.д. и т.п.
А так просто обсуждать - это "гнилой базар" (с) Папа :-)
vg
Маньяк
Сообщения: 2803
Зарегистрирован: 29 май 2003, 22:29
Откуда: Магадан - Миссиссага

Сообщение vg »

2Mark,

Если задача такова, как у тебя (теперь я понял, что у тебя) – нет вопросов. Ничего искать и не надо. Конечно – только на сокетах. И обсуждать там нечего, кроме, возможно, некоторых технических деталей. И спрашивал я не про это. Хотя некоторые свои комментарии ниже добавлю.
1. Протокол может быть ЛЮБОЙ! Все зависит от конкретной задачи.
Задача, решение которой мне интересно, как мне показалось, достаточно ясно «нарисована» в моём постинге выше.
2. Посмотри внутрь профессионально написаных протоколов апп уровня, типа ФТП, СМТП, итп. КТО ВО ЧТО ГОРАЗД!
Хорошие протоколы. На счёт того, что реализации их действительно бывают разные – ты прав. Но к рассматриваемой теме мало относится. Нечего особо в реализациях этих протоколов смотреть. Разве, что можно по исходникам поучиться программировать.
Говорю ж, тот код, который я приводил выше, работает. Надёжно и эффективно. Но в LAN. В инет это не будет работать (надёжность останется. Эффективность - нулевая).
Я спрашивал в надежде найти что нибудь наиболее стандартное. Не нашел. Мой сервис работает с сугубо текстовыми данными. Поэтому HTTP подошел бы более всего. Но он "односессионный". Т.е. один запрос/ответ на сессию. Можно сэмулировать многозапросную сессию и на ХТТП, но это излишнее усложнение по сравнению с "голыми" сокетами и "самопальным" протоколом.


Для того, что я прочитал в твоём псевдокоде – одной сессии достаточно, imxo. Если мы говорим об одном и том же. Я об установленном соединении TCP. Ты, похоже, говоришь о том, что в одной «сессии» ты просто делаешь более одного запроса (на прикладном, а не транспортном уровне). Но всё равно TCP соединение одно, извини за нудность.
И еще почему я хотел готовый протокол, чтобы использовать уже наработанный софт для его реализации. Энжин какой нибудь, типа сервлетного. К сожалению ничего не подошло. Апачевский Авалон наиболее близок, но сильно уж сложен для мой задачи. Как из пушки по воробъям.
Понятно. Непонятно только, чего ты сомневался- «на чём писать»;))) Конечно две страницы С-текста на сокетах.;)))
Короче, я открываю сокет и обмен идет на "словах", тэгах.
Да совершенно всё равно. Ты не выиграл, не проиграл. Замена строк команд (для твоего случая, разумеется) на символические числовые команды не даст ни сколько повышения производительности. Но я бы использовал числовые команды.
begin session
1. CLIENT:PUPKIN
2. SEVER:OK
3. CLIENT:GETTHING
4. thing
5. CLIENT:OK
end session

Примитивно? Меня устраивает.
Нет не примитивно. Меня бы, наверное, тоже устроило.
Возможно можно было бы сделать "язык" в бинарном виде.
Совершенно незачем в твоём случае, если душа не лежит к этому.
Было бы компактно.
Брось. Не смеши. Оверхед уменьшишь на 0, ххх %
Но не удобно в поддержке. Или в XML. Было бы модно.
И настолько же бесполезно. (я даже знаю, кого сейчас вспоминает Мармот;)))

ПС. Всё ты сделал правильно. Но думаю, в твоём случае вряд ли можно было б сделать по-другому. Хотя на этом форуме есть любители.

2Marmot,
А вот у меня нету едиственного ответа на это вопрос.
Ты давай не отлынивай. Я тебе верю так же, как Вузи. Вынимай свой мечь-кладенец. Биться будем.
Я на жизнь зарабатываю как System Architect и, из своего опыта знаю, что это зависит от очень большого количества факторов.
Ну, очень ты мне содержательно ответил. Очень.
В каждом случае надо конкретно разбираться, чего люди хотят, знают, умееют, на чём будет бегать, и т.д. и т.п.
Знаю и умею мало. Ты, думаю, об этом, подозреваешь. Это не рисовка. Ты спец. Вряд ли тебе можно по ушам повтирать. Мне действительно интересны некоторые аспекты этой задачи. И эти аспекты не кажутся мне простыми. Вернее сказать для меня там – тупик. Пока тупик.
А так просто обсуждать - это "гнилой базар" (с) Папа
ООО!!! Совсем ты Папика Карлика не боишься, или он тебе дал индульгенцию?
The more you know,
the more you hurt;
the more you understand,
the more you suffer.
Мне надо признать свою ошибку. Я как-то намекал, что ты не умеешь красиво говорить. Я был неправ. Это мне понравилось. Серьёзно.

ПС. Я понял тебя Мармот. Но прямо сейчас не могу «конкретизировать» свой вопрос в топике, чтоб это был не флейм (по мнению ваших «гнилой базар»), а предметное обсуждение. Надо сформулировать вопросы.
Аватара пользователя
Marmot
Графоман
Сообщения: 38419
Зарегистрирован: 17 фев 2003, 17:58
Откуда: Canyon Heights
Контактная информация:

Сообщение Marmot »

vg писал(а):
The more you know,
the more you hurt;
the more you understand,
the more you suffer.
Мне надо признать свою ошибку. Я как-то намекал, что ты не умеешь красиво говорить. Я был неправ. Это мне понравилось. Серьёзно.
Ок, срочно исправляюсь... :lol:
MarkM
Пользователь
Сообщения: 113
Зарегистрирован: 24 сен 2003, 21:52

Re: Спортивный сокетный интерес

Сообщение MarkM »

vg писал(а):Вот схожие ситуации, где я бы тоже не отвечал с учётом их тривиальности:
1) читаем и пишем в таблицы, структура которых известна клиенту «заранее». При этом ещё лучше, если MEMO и BLOB – отсутствуют. Скорее всего, и клиента и сервер здесь проектирует один и тот же человек.
2) пишется протокол под «конкретную» задачу. Есть вполне определённая база. Клиент обращается к серверу не с SQL запросами, а с запросами типа – GET_FOLDERS, GET_DEPARTMENTS. Приблизительно так построено приложение «1C Архив» (если я правильно понял, промониторив сетефой трафик). Совершенно классное и эффективное Российское приложение.

Но мне хотелось выяснить: «Каким должен быть протокол, если предполагается решение более сложных задач? Например, клиентские приложения работают по инет с DBMS так, как если б клиенты использовали DCOM в LAN c Windows-машинами. Задают SQL вопросы и получают достаточно быстро достойные SQL ответы».
ВНИМАНИЕ ВОПРОС:

Каким должен быть протокол, если это не LAN, а инет?
[trn]
Nuu, eto davno uzhe vydumano. Vse propraitori Klient-Server protokoly ochen' ekonomichny v setevom aspekte. SQL zapros - SQL otvet.
Dlja uhoda ot "propraitornosti" vydumaly ODBC, JDBC, XML.
Ser'jeznoe setevoe App, s mnogochislennymi _gibkimi_ zaprosami nado delat' na ODBC/JDBC ili SQL vopros - XML otvet. Ili dazhe XML - XML.
Nemnogo hudshij setevoj performans budet platoj za bOl'shuju gibkost' i masshtabiruemost'. I NIKAKIX DCOM!

PS/ v "moem" sluchae ne nuzhna osobo ni gibkost' ni standartnost', poetomu ja izbral "staryj-dobryj" "voennyj" podhod.
[/trn]
Аватара пользователя
Marmot
Графоман
Сообщения: 38419
Зарегистрирован: 17 фев 2003, 17:58
Откуда: Canyon Heights
Контактная информация:

Re: Спортивный сокетный интерес

Сообщение Marmot »

MarkM писал(а):Нуу, ето давно уже выдумано. Все пропраитори Клиент-Сервер протоколы очень економичны в сетевом аспекте. СQЛ запрос - СQЛ ответ.
Для ухода от "пропраиторности" выдумалы ОДБЦ, ЙДБЦ, XМЛ.
Серьйезное сетевое Апп, с многочисленными _гибкими_ запросами надо делать на ОДБЦ/ЙДБЦ или СQЛ вопрос - XМЛ ответ. Или даже XМЛ - XМЛ.
Немного худший сетевой перформанс будет платой за бОльшую гибкость и масштабируемость. И НИКАКИX ДЦОМ!

ПС/ в "моем" случае не нужна особо ни гибкость ни стандартность, поетому я избрал "старый-добрый" "военный" подход.
Вот только не надо путать разные вещи:
ODBC/JDBC это API (not protocol), network protocol in both cases is vendor specific
XML - this is data format, not protocol again
DCOM is a Distributed Component Object Model

Протоколы это: HTTP, SOAP, SMTP, Net8, IIOP,DCOM wire protocol, самоделка ;-), etc.

В общем случае, в настоящее время, игнорируя специфику задачи, я бы посоветовал начать с рассмотрения SOAP over HTTP.
MarkM
Пользователь
Сообщения: 113
Зарегистрирован: 24 сен 2003, 21:52

Re: Спортивный сокетный интерес

Сообщение MarkM »

Marmot писал(а):Вот только не надо путать разные вещи:
ODBC/JDBC это API (not protocol), network protocol in both cases is vendor specific
XML - this is data format, not protocol again
DCOM is a Distributed Component Object Model

Протоколы это: HTTP, SOAP, SMTP, Net8, IIOP,DCOM wire protocol, самоделка ;-), etc.
Если быть точным то да. А то все смешалось в доме облонских.
Marmot писал(а): В общем случае, в настоящее время, игнорируя специфику задачи, я бы посоветовал начать с рассмотрения SOAP over HTTP.
Ну не знаю, не знаю. Для вг возможно да, SOAP. Но он будет менее эффективным чем Net8.
Аватара пользователя
Marmot
Графоман
Сообщения: 38419
Зарегистрирован: 17 фев 2003, 17:58
Откуда: Canyon Heights
Контактная информация:

Re: Спортивный сокетный интерес

Сообщение Marmot »

MarkM писал(а):
Marmot писал(а): В общем случае, в настоящее время, игнорируя специфику задачи, я бы посоветовал начать с рассмотрения SOAP over HTTP.
Ну не знаю, не знаю. Для вг возможно да, SOAP. Но он будет менее эффективным чем Net8.
Net8 через типичный firewall хрен проидёт...
vg
Маньяк
Сообщения: 2803
Зарегистрирован: 29 май 2003, 22:29
Откуда: Магадан - Миссиссага

Сообщение vg »

Вначале лекарство (бить меня будете ниже. Там у меня вопросы будут).

*** ЛЕКАРСТВА ***
Marmot:

Вот только не надо путать разные вещи:
ODBC/JDBC это API (not protocol), network protocol in both cases is vendor specific
XML - this is data format, not protocol again
DCOM is a Distributed Component Object Model

Протоколы это: HTTP, SOAP, SMTP, Net8, IIOP,DCOM wire protocol, самоделка , etc.

Mark:

Если быть точным то да. А то все смешалось в доме облонских.
Я в некотором замешательстве в части точности формулировок.

http://www.microsoft.com/com/tech/dcom.asp
The Distributed Component Object Model (DCOM) is a protocol that enables software components to communicate directly over a network ...

или, например,

http://www.microsoft.com/msj/defaultfra ... 8/dcom.htm
We consider DCOM a high-level network protocol because it is built on top of several layers of existing protocols. For example, assume …

А вообще по этому поводу много было сказано в инете.

Mark
Ну не знаю, не знаю. Для вг возможно да, SOAP.
Думаю, нет. Обоснуй своё мнение. Что конкретного здесь даст соап ;)) Подробнее здесь, пожалуйста (Мармоту тоже не возбраняется здесь проявиться;))).

Marmot,
В общем случае, в настоящее время, игнорируя специфику задачи, я бы посоветовал начать с рассмотрения SOAP over HTTP.
А зачем? Обоснуй. Что это даст в контексте обсуждаемой задачи? Если говорить только о практическом аспекте, как-то: нужно решить задачу и всё тут, - так только http и достаточно. И клиента не надо. Будем смотреть «базу» IE.

Marmot,
Net8 через типичный firewall хрен проидёт...
Не горячись. Я не знаю, что такое Net8. Но! Eсли сетевым протоколом остаётся ip – то «пройдёт» всё, что захочет системный администратор (ры – в корпоративной среде). Ты уж мне поверь здесь.


Mark,
ПС/ в \"моем\" случае не нужна особо ни гибкость ни стандартность, поетому я избрал \"старый-добрый\" \"военный\" подход.
Я уже говорил один раз, что ты сделал нормально. Рейтинг свой повышаешь? ;)))

1. *** МАЛЕНТКИЕ ВОПРОСЫ К РЕАЛИЗАЦИИ ***

Поскольку по-большому разобраться не получается, попробуем по-маленькому. Мне немного непонятно, почему вам, уважаемые, непонятно в чём косяк может быть в том коде, который я пропостил первый раз. Оставим на «потом». Я попробую конкретизировать ещё, для дополнительной «затравки», некоторые (но не все) аспекты. Хотя они и не основные, но разобраться хочется. Тем более, что это вопросы общего характера, с которыми сталкивался каждый программист в «повседневке». Это не офтоп. Все вопросы по теме.

В реализации клиента и сервера всё как бы обыденно. Обсуждать особо нечего. Может только некоторые детали ниже. И сервер, и клиент - на блокирующих сокетах. Интерфейс Беркли. Асинхронные штучки в реализации сокетов в Windows здесь не использую (пока). Сервер – многопоточный (каждого клиента обслуживаем в отдельном потоке).

1.1 Потоки клиентов.
Зная свою слабость к большому числу ошибок в коде, решил не оставлять потоки клиентов «безнадзорными». Кое-что здесь уже сделано. Кое-что не стал делать (для «спортивного интереса» было б слишком). Есть пул потоков, который можно контролировать из специального потока-свиппера «менеджера клиентских потоков». Для описания клиентского потока используем структуру CLIENTINFO:

Код: Выделить всё

#define MAXCLIENTS		512
#define MAX_CLIENTQUERYES	10


typedef struct _iclientquery
{
	_DWORD		hQuery;	// дескриптор объекта доступа
				// к набору данных DBMS
	_DWORD		status;	// статус оъекта (создан/открыт/закрыт...)
	IQueryInterface*	IQuery;	// указатель на интерфейс объекта
	…
	…
}
IQUERY;


typedef struct _clientinfo
{
	HANDLE		hThread;	// дескриптор потока
	_BYTE		ThreadState;	// статус потока
	SOCKET		sock;		// клиентский сокет
	_DWORD		addr;		// ip клиента
	
	_BYTE		*stream_buf;	// буфер ввода/вывода клиента
	_DWORD		cur_bufsize;	// текущий размер буфера

	IQUERY		querylist[MAX_CLIENTQUERYES];
	_WORD		nqueryes;
	…
	…
}
CLIENTINFO;

typedef CLIENTINFO*		PCLIENTINFO;
Каждый клиентский поток регистрируется при его создании (спящим). После того, как данные, необходимые клиенту заполнены (структура CLIENTINFO, указатель на которую уже передан потоку при его создании) – будим поток.

Код: Выделить всё

while((client_socket=accept(srv_socket, (sockaddr *) &client_addr, &client_addr_size)))
{
	PCLIENTINFO sockinfo = allocinfo();
	if ( !sockinfo ) { 
		printf("\n\aAllocation error. Close connection.");
		byeclient( client_socket );
		continue;
	}
…
…
	unsigned thID;
	uintptr_t hThread = _beginthreadex( NULL, 0, &ClientThread, sockinfo, CREATE_SUSPENDED,  &thID );
	
	if (! hThread)
	{
		printf("\n\aCreating client thread error. Close connection.");
		byeclient( client_socket );
		freeinfo( sockinfo);
		continue;	
	}
	
	sockinfo->sock			= client_socket;
	sockinfo->addr			= client_addr.sin_addr.S_un.S_addr;
	sockinfo->hThread		= (HANDLE) hThread;
	sockinfo->ThreadState		|= THS_CREATED | THS_SUSPENDED;

	if (ResumeThread( (HANDLE) hThread ) != -1L)
		sockinfo->ThreadState &= ~THS_SUSPENDED;
	…
	…
}
Доступ потока-свиппера к пулу быстрый, без существенной блокировки потоков клиентов. Свиппер будет искать и чистить подвисшие потоки по такому сценарию. В критической секции (сама по себе быстрая) можно выполняем «моментальный снимок» - копию пула. Затем, «отпустив» критическую секцию, можно уже в копии пула искать процессы-зомби по некоторому критерию (скорее всего – некоторый таймаут клиентского потока, который по типу «жив/не жив» контролируется из клиентского потока), и если таковые найдутся, то в свиппер-потоке: приостановить клиентский поток, почистить его ресурсы (буфер ввода/вывода, открытые наборы данных DBMS, объекты доступа к данным DBMS) и потом уж - убить подвисший поток. Останется быстро вторым вхождением в критическую секцию почистить реальный пул с CLIENTINFO уже задавленного потока-зомби. Взаимных продолжительных блокировок клиентских потоков не будет. Клиентский поток обращается к пулу в критической секции только один раз и на очень короткое время – для освобождения своего дескриптора и саморазрегистрации (удаления себя из пула потоков) непосредственно перед завершением функции потока.
Как думаете нужен ли свиппер, и какой?

Здесь было сказано о буфере ввода/вывода клиентского потока, см. stream_buf в структуре CLIENTINFO выше. Вообще, на мой взгляд, это вопрос – как выделять память потоку для буфера ввода/вывода? В той реализации, которая сделана из «спортивного интереса» – сделано дубово. Память выделяется в одной, общей куче процесса. Какие идеи в части памяти, господа?

1.2 Буфер ввода/вывода клиентского потока.
Неожиданно наткнулся на вопрос, на который раньше не обращал внимания. Выше, в п. 1.1 сказано, что память для буфера ввода/вывода клиентского потока выделяется из одной кучи процесса. Сам по себе вопрос. Другой вопрос связан с тем, как выделяется? Проще и быстрее всего, с точки зрения доступа – realloc (поэтому-то и realloc). Алгоритм здесь, казалось бы, может быть совсем простым – вычитываем из заголовка «сообщения» его размер (размер заголовка плюс данные), и делаем realloc требуемого размера. Сомнения здесь связаны с возможной фрагментацией памяти из большого числа клиентских потоков, и как следствие с общим кирдык. В случае, когда каждый из клиентских потоков сервера будет «шинковать» память процесса для маленьких «сообщений», мне кажется, что возможна ситуация, когда память будет нарезана, как рулетик. Пока я сделал тупо – память выделяется блоками кратными 1024 и в два раза больше, чем было запрошено, если текущий буфер мал. При следующем запросе вначале проверяем текущий размер буфера, и если «сообщение» помещается, то realloc не делаем вовсе. Какие идеи, господа?
У меня – никаких нормальных.

1.3 Клиент.
В работе клиента есть одна особенность – возможно большие таймауты, когда пользователь пошёл покурить. Т.е. соединились, прочитали что надо, а дальше юзвер ничего не делает. Просто рвать соединение по таймауту, пусть даже достаточно большому, на мой взгляд неразумно. Молчание клиента может быть связано как с тем, что клиент «курит», так и с тем, что клиентская сторона подвисла. Именно подвисла, а не разрушила сокет, разорвала соединение и т.д., что серверная сторона заметит по клиентскому сокету на своей стороне. Другие патологические ситуации, когда клиент исчез, оставив полуоткрытое соединение на конце сервера, а сервер ожидает каких-либо данных от клиента, здесь я не рассматриваю. Хотя и это может быть. Единственное решение в этой ситуации, на мой взгляд – это пинги пингать. Опция TCP keepalive вряд ли поможет. Да и не рекомендуют её гуру в Host Requirements RFC. Не гуру, но практики на форумах так же замечают, что реальное время таумаута keepalive в различных реализациях и конфигурациях TCP может быть различным - 1,5 – 2 и более часов. Мутно всё это.
Таким образом, мне кажется, что в любом мало-мальски нормальном прикладном протоколе, рассчитанном на длительные соединения (имеется ввиду только TCP, а не соединения с DBMS) обрабатывать длительные таймауты следует самостоятельно. Не проблема это включить в обсуждаемый протокол. Не очень ясно другое, как это сделать в реализации сервера и клиента. Например, на клиенте придётся или делать это в отдельном потоке (все данные и получаем и отсылаем в отдельном потоке) – изврат, или использовать асинхронные сокеты Windows в сочетании с таймерами (для организации обычных таймаутов чтения/записи в сокет).
Какие идеи, господа?

2. *** ДОПОЛНИТЕЛЬНЫЕ ВОПРОСЫ ***
Совсем простые вопросы. Хочется узнать ваше мнение, уважаемые.

2.1 Сетевой порядок байт.
В простейшем случае запрос/отклик состоят из заголовка в 12 байт и возможно данных (если таковые необходимы). Формат заголовка запроса и отклика одинаков:

Код: Выделить всё

|  msg_size (32  bit) – общий размер «сообщения» |  command  ( 8   bit ) – код команды запроса |  param ( 8   bit ) – параметр команды (пока у меня всегда  0) |  checksum  ( 16  bit ) – контрольная сумма |  error  ( 32  bit ) – код результата запроса |


typedef struct _appheader
{
	_DWORD	msg_size;		/* 32  bit */
	_BYTE	command; 	/* 8   bit */
	_BYTE	param; 		/* 8   bit */
	_WORD	checksum; 	/* 16  bit */
	_DWORD	error; 		/* 32  bit */
//	_BYTE	reserved[HDRPADDING]; /* HDRPADDING bytes of trailing padding */

} APPHEADER;			/* 12  bytes */
ООО!!! Неоднократно встречал на форумах, в том числе и в faq-ах от гуру, что, дескать, не забывайте, ламеры, про сетевой порядок байт. Зачем?!!! Наивные. Да у них (у гуру) крыша поехала. Это ж прикладной протокол. Какая здесь разница. Всё равно клиентов под разные платформы придётся компилировать отдельно. Там (на платформах отличных от Intel) и учесть можно – делать htons, или нет. Другие мнения есть?

2.2 Выравнивание заголовка по границе слова.
Имеется в виду то, обстоятельство, что если в будущем пришлось бы убрать из заголовка, например, _BYTE param (за ненадобностью), то хорошо б было добавить закомментированное выше reserved, см.заголовок выше.
Не вижу большого смысла, ибо напоминает это мне «мастерство» типа замены операции « a / 2 » побитовым «a >> 1». Хотя сомнения, конечно, есть небольшие. Заголовок вычитывается из сокета «первым». Здесь не так важно сколько читать – 11 байт, или 12. Другое дело, насколько эффективным будет следующий шаг – вычитывание «невыровненных» данных (что за заголовком) из буфера сокета.
Какие будут мнения, товарищи?

2.3 Выравнивание полей в заголовке.
Похоже на предыдущий пункт. И здесь логики больше. Хотя, тоже с учётом возможностей современных компиллеров, сомнительно. Речь идёт о том, что слово выравниваем по границе слова, а двойное слово – по границе двойного слова. Придерживаюсь пока правил. А по правде – насколько это актуально сейчас (чай не 80-е годы на дворе)?

2.4 Контрольная сумма.
Есть некое противоречие между потоковой природой сокетов TCP и желанием программиста работать с потоком, как с набором «сообщений». «Ненадёжность» здесь может быть связана с ошибками в коде сервера или клиента, когда, грубо говоря, будем читать «заголовок» следующего сообщения, не дочитав из потока ещё данные предыдущего сообщения. Подчёркиваю, речь не о том, что данные придут не в том порядке, неполностью или искажёнными (это невозможно, поскольку контрольные суммы и IP, и, главным образом, TCP – гаранты надёжности), а о только том, чтобы программер правильно «вычитавал» заголовок, а потом данные. Чтобы он не считал мусор – заголовком.
Здесь для повышения надёжности протокола можно было б вычислять контрольную сумму по заголовочной информации (без данных). Поле checksum, см. структуру заголовка APPHEADER выше, – это контрольная сумма. Пока вычисляю и использую. На стадии отладки кое-где помогало. Хочу с вами посоветоваться о нужности его вообще в прикладных протоколах, и в обсуждаемом протоколе в частности. Алгоритм вычисления – стандартный, как в IP, или в TCP/UDP. Как и в IP при вычислении контрольной суммы данные не учитываются (считаем только заголовочные данные). Однако в отличие от протокола IP, расчёт ведётся с учётом псевдохедера (как в TCP/UDP). Алгоритм и структура псевдозаголовка соответствует таковым в RFC (но в отличие от TCP/UDP данные не учитываются). Структура псевдохедера:

Код: Выделить всё

typedef struct
{
	_DWORD	saddr;		/* 32  bit */
	_DWORD	daddr;		/* 32  bit */
	_DWORD	len;		/* 32  bit */
	_BYTE	zero;		/* 8   bit */
	_BYTE	proto;		/* 8   bit */
}
PSEUDOHDR;			/* 14  bytes */
Здесь при вычислении контрольной суммы в поле len помещаю значение поля msg_size реального заголовка. Поле proto – порт, который «слушает» сервер.

Вставляется эта проверка движением руки. Потери производительности – никакой. А сомнения здесь такого рода – хорошо «вылезанный» код не требует проверки checksum. На форумах вообще не слышал, чтобы кто-то так делал. Отсюда, думаю, - а не усложняю ли я понапрасну здесь всё. Единственное, что могу привести в свою защиту – так и в первых реализациях UDP не вычисляли контрольную сумму.
Как думаете вы, уважаемые?
Аватара пользователя
Marmot
Графоман
Сообщения: 38419
Зарегистрирован: 17 фев 2003, 17:58
Откуда: Canyon Heights
Контактная информация:

Сообщение Marmot »

vg писал(а): Я в некотором замешательстве в части точности формулировок.

http://www.microsoft.com/com/tech/dcom.asp
The Distributed Component Object Model (DCOM) is a protocol that enables software components to communicate directly over a network ...
А это ты сам с БГ разбирайся как это Object Model может быть network protocol
Если ты заметил, я там в списке написал "DCOM wire protocol", imho это и есть точное определение.
vg писал(а):

В общем случае, в настоящее время, игнорируя специфику задачи, я бы посоветовал начать с рассмотрения SOAP over HTTP.
А зачем? Обоснуй. Что это даст в контексте обсуждаемой задачи? Если говорить только о практическом аспекте, как-то: нужно решить задачу и всё тут, - так только http и достаточно. И клиента не надо. Будем смотреть «базу» IE.
При наличии стандатных библиотек и тулзов пишется и деплоится за пару часов :-)
Что значит клиента не надо, я не въехал?
vg писал(а):
Net8 через типичный firewall хрен проидёт...
Не горячись. Я не знаю, что такое Net8.
Гуглом, я так понимаю, мы тоже пользоваться не умеем?
vg писал(а): Но! Eсли сетевым протоколом остаётся ip – то «пройдёт» всё, что захочет системный администратор (ры – в корпоративной среде). Ты уж мне поверь здесь.
Я могу поверить тебе ТАМ, а вот здесь это не пройдёт :-)
И это я тебе скажу на 200%, как человек работающий на очень ответственные организации.
Дай бог, что бы пустили хоть HTTP снаружи, да ещё и месяца 3 будешь бумажки писать, объясняя зачем тебе это надо...
Вот именно поэтому все так и полюбили это гнилой SOAP, что на HTTP firewall admin-ов ещё можно уломать.
А вот скоро они разберутся что SOAP это тоже дырка и лажа закончится.

vg писал(а):
Я попробую конкретизировать ещё, для дополнительной «затравки»,
...
Как думаете вы, уважаемые?
Не надо так много писать, надо много читать, это гораздо полезнее.
И откроется вам истина :-)
Что всё уже давно написано, надо только уметь этим пользоваться.
vg
Маньяк
Сообщения: 2803
Зарегистрирован: 29 май 2003, 22:29
Откуда: Магадан - Миссиссага

Сообщение vg »

Мармот,
Когда я говорил: «Доставай свой меч – кладенец биться будем», - я ж не кувалду имел ввиду :lol: . Ну и чего ты разошёлся. До такой степени, что даже меня вместо ВГ – БГ обозвал.
:lol: :lol:
Что значит клиента не надо, я не въехал?
Есть www. Там, рядышком в www - SQL сервер обирает, где некая база данных, например, по полезным ископаемым. Пользователь использует IE - смотрелку. Самодельных клиентов не требуется. :lol:
А для сисадмина - просто песня. И всё безопасно, как ни странно. :wink:
Вот именно поэтому все так и полюбили это гнилой SOAP, что на HTTP firewall admin-ов ещё можно уломать.
Да, просто то такие админы. Опасностей много. Надо просто знать, что опасно, а что нет. Есть много средств, которые позволяют сделать инет менее опасным. Зря мне не веришь.

ПС. Там у меня конкретные вопросы по программированию. Вопросы написаны длинновато. Не отрицаю. Не хочешь - не отвечай. :lol:
vg
Маньяк
Сообщения: 2803
Зарегистрирован: 29 май 2003, 22:29
Откуда: Магадан - Миссиссага

Сообщение vg »

Господа, кто хочет написать в эту нитку!

Если можно, то прошу учесть вопрос топика «А каким должен быть прикладной протокол, определяющий информационный обмен клиент/серверного приложения, написанного «на сокетах»?».
Имеется ввиду приложения DBMS.
Yocto
Частый Гость
Сообщения: 36
Зарегистрирован: 07 окт 2003, 11:06

Сообщение Yocto »

Marmot писал(а):Вот именно поэтому все так и полюбили это гнилой SOAP, что на HTTP firewall admin-ов ещё можно уломать.
Админа, которого надо на что-то там уламывать, надо гнать к соответствующей матери.
Или, как вариант, не работать в компании, где разрешениями заправляет админ.
MarkM
Пользователь
Сообщения: 113
Зарегистрирован: 24 сен 2003, 21:52

Re: Спортивный сокетный интерес

Сообщение MarkM »

Marmot писал(а):Net8 через типичный firewall хрен проидёт...
[trn] Projdet, projdet.
Gde ne projdet, tam mozhno cherez Connection Manager propustit'.
[/trn]
Ответить