Как написать tcp сервер ?

Discussion in 'Hardware and Software' started by Sashan, Mar 25, 2003.

  1. Sashan

    Sashan Well-Known Member

    Joined:
    Dec 18, 2001
    Messages:
    279
    Location:
    Novosibirsk, Russia
    Как написать tcp сервер ?

    Народ... судя по опросам программистов здесь хватает... может кто поделится соображениями/знаниями.

    Как писать сервер, подобный WB ?
    Сразу скажу, FH писать я не собтраюсь :) ... пока пишу простенькую мультиплеерную аркаду с танчиками.... так вот :
    На блокирующих коннектах я предполагаю... На каждый коннект - thread, синхронизировать их надо наверно. ...
    Как организовать чат, понятно.
    А вот как организовать обмен данными в РВ (координаты противников, стрельба, повреждения)... как работет сервер и клиент, кто инициирует передачу данных ? : то ли клиент говорит что мне нужна новая пачка данных, или сервер шлёт эти данные, без всяких просьб клиента.... ? И кстати, в WB используется один или несколько портов для разных типов пакетов ?
    Может кто поделится знаниями/соображениями/ссылками ? Только не DirectPlay !!!
     
  2. Ivan_004

    Ivan_004 Well-Known Member

    Joined:
    Jun 18, 2002
    Messages:
    613
    Я как-то делал сервер, правда не игровой :). В общем если речь идет об NT-платформе, могу посоветовать следующее:

    1) не использовать 1 коннект - 1 thread, imho слишком нерационально, поскольку переключение контекста и все такое. Я использовал файберы, при этом определял заранее число threads (настройками) и использовал completion ports. Скажем модель выглядит примерно так есть пул из 10 threads , на каждого клиента - создается файбер, при инициации запроса свободный поток переключает контекст (каждый клиент(коннект) имеет свой контекст), и переключается на соответствующий файбер.
    2) на сервере лучше делать асинхронную обработку, но это довольно сложно реализовать.
    3) взаимодействие клиента с сервером я делал примерно так:
    у сервера была подсистема ввода-вывода, которая могла получить прерывание как со стороны клиента, так и со стороны подсистемы следующего уровня. что-то вроде стека tcp.
    - сервер в режиме ожидания запроса клиента
    - запрос получен, асинхронное чтение
    - чтение завершено, запрос отправлен подсистеме верхнего уровня
    - проверка очереди, если есть сообщения в очереди - асинхронная запись на клиента
    - закончена запись, переход в режим чтения
    перевод в режими чтения-записи зависят от состояния контекста сессии. т.е. если был получен запрос, сессия переводится в состояние ожидания ответа и чтение не производится до окончания обработки.

    вот примерно так. Но это была специфика сервера, это был сервер обработки запросов, (например sql server), в данном случае не знаю подойдет ли тебе такая схема.
     
  3. Sea

    Sea Well-Known Member

    Joined:
    Feb 9, 2001
    Messages:
    27,702
    Location:
    Ukraine, Kiev
    Посмотри http://plib.sourceforge.net/ там есть уже готовая библиотека для сетевой игры. Компилится и для винды (visual C).

    Там вообще много чего интересного есть :) сам уже пол-года сижу, втыкаю :) с документацией там не очень :(
     
  4. Sashan

    Sashan Well-Known Member

    Joined:
    Dec 18, 2001
    Messages:
    279
    Location:
    Novosibirsk, Russia
    Спасибо, я его смотрел, когда с Flightgear пробовал разобраться ... но если честно, не очень понравилось - именно изза отсутствия хорошей документации.... конечно плюс что многоплатформенная, но расчитанно всё именно на гуру... ну а стал-бы я спрашивать, если-бы я им был в этом вопросе ? :)

    Но спасибо в любом случае.... я всётаки её ещё посмотрю :)

    ps ...Но как ломает копаться в чужом коде :)
     
    Last edited: Mar 25, 2003
  5. Sea

    Sea Well-Known Member

    Joined:
    Feb 9, 2001
    Messages:
    27,702
    Location:
    Ukraine, Kiev
    Ну только с net модулем разобратся не сложно, тем более что там для этого есть простенькие примеры. Вот с остальным - напряжно, хотя примеры помогают. Весь вопрос, на сколько этот модуль там реализован :)
     
  6. Sashan

    Sashan Well-Known Member

    Joined:
    Dec 18, 2001
    Messages:
    279
    Location:
    Novosibirsk, Russia
    2 Ivan...

    Ну во первых, конечно спасибо !!!

    А во вторых -

    А почему тхреды нерационально ? Ну контекст, и ладно. Файберы нужно самому по хитрому переключать (я с ним реально не работал)... а тхреды - написал один и забыл, они сами средстами ОС распаралелятся ... тем более под линуксами (хотелось чтобы и там работало) они оптимальнее (имхо) работают...

    Насколько я понимаю та схема, которую предложил ты - хороша для серверов, где отдельно взятый коннект поработал немного, и ушёл в идл (без отключения), и может висеть там сколько угодно. Тогда пул имеет смысл. А коннекты к игровому серверу постоянно активны, и боюсь, что при работе с файберами нет гарантии, что "дохлый" коннект не подвесит остальных.
     
  7. PressLuftHammer

    PressLuftHammer FH Beta Tester

    Joined:
    Mar 5, 2003
    Messages:
    15,084
    Location:
    Ekaterinburg (Russia)
    По идее можно юзать UDP там необходимости в создании потоков для каждого соединения нету максимум один поток.
    Елинственно нужно отслеживать подключение нового пользователя по IP+Port и прекращение работы с ним с кажем если запросы от него не приходили в течении какого то времени.
    При этом пропадает необходимость в синхронизации потоков при обращении кобщим данным, и накладные расходы на их переключение.
     
  8. Bobby

    Bobby Well-Known Member

    Joined:
    Oct 19, 2001
    Messages:
    9,757
    Location:
    Almaty, Kazakhstan
    Code:
    rad_select()
    {
    	int                     result;
    	int                     status;
    	int                     salen;
    	struct	sockaddr	saremote;
    	fd_set			readfds;
    	struct socket_list      *ctl;
    	
    	FD_ZERO(&readfds);
    	for (ctl = socket_first; ctl; ctl = ctl->next) 
    		FD_SET(ctl->fd, &readfds);
    
    	status = select(max_fd, &readfds, NULL, NULL, NULL);
    	if (status == -1) {
    		if (errno == EINTR)
    			return;/* give main a chance to do some housekeeping */
    		rad_exit(101);
    	}
    	
    	for (ctl = socket_first; ctl; ctl = ctl->next) {
    		if (FD_ISSET(ctl->fd, &readfds)) {
    			salen = sizeof (saremote);
    			result = recvfrom (ctl->fd, (char *) recv_buffer,
    					   (int) sizeof(i_recv_buffer),
    					   (int) 0, &saremote, &salen);
    
    			if (ctl->success)
    				ctl->success(&saremote, salen);
    			if (result > 0) {
    				ctl->respond(ctl->fd,
    					     &saremote, salen,
    					     recv_buffer, result);
    			} else if (result < 0 && errno == EINTR) {
    				if (ctl->failure)
    					ctl->failure(&saremote, salen);
    				result = 0;
    			}
    		}
    	}
    }
    
    
    это кусок кода из gnu-radius отвечает за чтение данных из сокета и ответ на него.
     
  9. PressLuftHammer

    PressLuftHammer FH Beta Tester

    Joined:
    Mar 5, 2003
    Messages:
    15,084
    Location:
    Ekaterinburg (Russia)
    Интересно какой протокол используется в WB и AH, UDP или TCP и какие порты ?
     
  10. Stefan

    Stefan FH Beta Tester

    Joined:
    Feb 14, 2001
    Messages:
    22,283
    Location:
    Пивбар
    В WB только TCP в АН TCP и UTP.
    Перемещения самолёта идут по UTP, ганери по ТСР
    Вроде так.
     
  11. Sashan

    Sashan Well-Known Member

    Joined:
    Dec 18, 2001
    Messages:
    279
    Location:
    Novosibirsk, Russia
    Имхо какраз наоборот координаты по tcp, а стрельба по udp.
     
  12. dankes

    dankes Well-Known Member

    Joined:
    Dec 13, 2001
    Messages:
    1,245
    Location:
    Moskau
    ИМХО прав таки Стефан.

    Если бы стрельба была по УДП, там бы все летали поливали друг друга пингами по 20 30мм болванок Ж)
     
  13. PressLuftHammer

    PressLuftHammer FH Beta Tester

    Joined:
    Mar 5, 2003
    Messages:
    15,084
    Location:
    Ekaterinburg (Russia)
    IMHO все таки стрельба по UDP он пошустрей будет чем TCP.
    Хотя может и ошибаюсь.
    Кстати интересно зачем использовать два протокола неужели UDP мало ?
     
  14. Stefan

    Stefan FH Beta Tester

    Joined:
    Feb 14, 2001
    Messages:
    22,283
    Location:
    Пивбар
    По UTP пакеты не маркируются. И у UTP нет подтверждения о доставке. Так что ганери по ТСР
     
  15. --oleg

    --oleg Well-Known Member

    Joined:
    Dec 20, 2001
    Messages:
    4,414
    Location:
    Russia
    Для стрельбы скорость передачи не важна, зато вожно, чтобы эти пакеты всегда доходили и не терялись по дороге. Поэтому для стрельбы используется TCP. А координаты самолетов передаются постоянно, если 1-2 пакета не дойдут - ничего страшного. Зато надо, чтоб они побыстрее доходили - меньше варпов и лагов будет. Соответственно - UDP.
     
  16. PressLuftHammer

    PressLuftHammer FH Beta Tester

    Joined:
    Mar 5, 2003
    Messages:
    15,084
    Location:
    Ekaterinburg (Russia)
    Понятно толко в том же IL-2 повидимому хватает одного UDP для того и другого. Кстати не уточните кикие порты используются по UDP у AH ?
    Есче один плюс о котором я здесть говорил относительно UDP это то что для его работы не нужно создавать по потоку на клиента в отличии от TCP что сводит к нулю издержки на переключение контекство и синхронизацию при чтении общих данных. Хотя наверное и там можно без потоков интересно в WB это реализовано на потоках или без ?
     
  17. --oleg

    --oleg Well-Known Member

    Joined:
    Dec 20, 2001
    Messages:
    4,414
    Location:
    Russia
    Я не в курсе, что там в Ил2 делается. В любом случае, никто не утверждает, что нельзя только UDP использовать. Гвозди, например, можно и пассатижами забивать ;)

    Там довольно много портов используется, какие точно - не знаю.

    Для TCP отдельные потоки тоже не обязательны. Просто это удобней программировать.
     
  18. PressLuftHammer

    PressLuftHammer FH Beta Tester

    Joined:
    Mar 5, 2003
    Messages:
    15,084
    Location:
    Ekaterinburg (Russia)
    Из тех игрушек что видел большинство всяких action и т.п работают именно по UDP.

    Для игр где требуется минимальное время отклика это грабли IMHO. Если переключение контекстов в win это 18.2 раза в секунду. То при сотне другой подключений ждать пакет придется долго :) Для FTP это конечно пофиг особенно когда там пакеты забиты под завязку и довольно большие, а вот для игр где критично время ответа может статься что не очень.
    Хотя возможно я сгущаю краски все таки пакеты приходят не одновременно и винда вида переключается только на те потоки что не находятся в состоянии оидания.
    Пусть меня поправят более грамотные в этом товарищи :)
     
  19. Sashan

    Sashan Well-Known Member

    Joined:
    Dec 18, 2001
    Messages:
    279
    Location:
    Novosibirsk, Russia
    Нееее.... Народ, вы путаете стрельбу и дэмедж.
    UDP - протокол без гарантии доставки. Такчто когда в AH видешь как кон пуляет - это именно udp (User Datagram Protocol)... ты можешь этого и не увидеть, если пакет не дошёл.

    А вот поврежения, которые он тебе напулял, позиции самолеётов, чат - tcp.... и если у тебя таймаут tcp - то это уже диско.

    Не разу не играл в ИЛ2 (стыдно признаться :)) но судя по описаниям - это обычный квейкоподобный сервер (только UDP) с интенсивным трафиком - нужен хороший канал (без потерь) - желательно лан, и небольшое (сравнивая с WB) количиество игроков.
     
  20. --oleg

    --oleg Well-Known Member

    Joined:
    Dec 20, 2001
    Messages:
    4,414
    Location:
    Russia
    Говорю тебе, как человек, у которого с 1.10 постоянно происходило переключение на TCP - координаты самолетов в АН изначально передаются по UDP. И если есть потери, то игра полностью переключается на TCP, т.е. вся инфа по нему начинает идти.