Как написать tcp сервер ? Народ... судя по опросам программистов здесь хватает... может кто поделится соображениями/знаниями. Как писать сервер, подобный WB ? Сразу скажу, FH писать я не собтраюсь ... пока пишу простенькую мультиплеерную аркаду с танчиками.... так вот : На блокирующих коннектах я предполагаю... На каждый коннект - thread, синхронизировать их надо наверно. ... Как организовать чат, понятно. А вот как организовать обмен данными в РВ (координаты противников, стрельба, повреждения)... как работет сервер и клиент, кто инициирует передачу данных ? : то ли клиент говорит что мне нужна новая пачка данных, или сервер шлёт эти данные, без всяких просьб клиента.... ? И кстати, в WB используется один или несколько портов для разных типов пакетов ? Может кто поделится знаниями/соображениями/ссылками ? Только не DirectPlay !!!
Я как-то делал сервер, правда не игровой . В общем если речь идет об NT-платформе, могу посоветовать следующее: 1) не использовать 1 коннект - 1 thread, imho слишком нерационально, поскольку переключение контекста и все такое. Я использовал файберы, при этом определял заранее число threads (настройками) и использовал completion ports. Скажем модель выглядит примерно так есть пул из 10 threads , на каждого клиента - создается файбер, при инициации запроса свободный поток переключает контекст (каждый клиент(коннект) имеет свой контекст), и переключается на соответствующий файбер. 2) на сервере лучше делать асинхронную обработку, но это довольно сложно реализовать. 3) взаимодействие клиента с сервером я делал примерно так: у сервера была подсистема ввода-вывода, которая могла получить прерывание как со стороны клиента, так и со стороны подсистемы следующего уровня. что-то вроде стека tcp. - сервер в режиме ожидания запроса клиента - запрос получен, асинхронное чтение - чтение завершено, запрос отправлен подсистеме верхнего уровня - проверка очереди, если есть сообщения в очереди - асинхронная запись на клиента - закончена запись, переход в режим чтения перевод в режими чтения-записи зависят от состояния контекста сессии. т.е. если был получен запрос, сессия переводится в состояние ожидания ответа и чтение не производится до окончания обработки. вот примерно так. Но это была специфика сервера, это был сервер обработки запросов, (например sql server), в данном случае не знаю подойдет ли тебе такая схема.
Посмотри http://plib.sourceforge.net/ там есть уже готовая библиотека для сетевой игры. Компилится и для винды (visual C). Там вообще много чего интересного есть сам уже пол-года сижу, втыкаю с документацией там не очень
Спасибо, я его смотрел, когда с Flightgear пробовал разобраться ... но если честно, не очень понравилось - именно изза отсутствия хорошей документации.... конечно плюс что многоплатформенная, но расчитанно всё именно на гуру... ну а стал-бы я спрашивать, если-бы я им был в этом вопросе ? Но спасибо в любом случае.... я всётаки её ещё посмотрю ps ...Но как ломает копаться в чужом коде
Ну только с net модулем разобратся не сложно, тем более что там для этого есть простенькие примеры. Вот с остальным - напряжно, хотя примеры помогают. Весь вопрос, на сколько этот модуль там реализован
2 Ivan... Ну во первых, конечно спасибо !!! А во вторых - А почему тхреды нерационально ? Ну контекст, и ладно. Файберы нужно самому по хитрому переключать (я с ним реально не работал)... а тхреды - написал один и забыл, они сами средстами ОС распаралелятся ... тем более под линуксами (хотелось чтобы и там работало) они оптимальнее (имхо) работают... Насколько я понимаю та схема, которую предложил ты - хороша для серверов, где отдельно взятый коннект поработал немного, и ушёл в идл (без отключения), и может висеть там сколько угодно. Тогда пул имеет смысл. А коннекты к игровому серверу постоянно активны, и боюсь, что при работе с файберами нет гарантии, что "дохлый" коннект не подвесит остальных.
По идее можно юзать UDP там необходимости в создании потоков для каждого соединения нету максимум один поток. Елинственно нужно отслеживать подключение нового пользователя по IP+Port и прекращение работы с ним с кажем если запросы от него не приходили в течении какого то времени. При этом пропадает необходимость в синхронизации потоков при обращении кобщим данным, и накладные расходы на их переключение.
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 отвечает за чтение данных из сокета и ответ на него.
ИМХО прав таки Стефан. Если бы стрельба была по УДП, там бы все летали поливали друг друга пингами по 20 30мм болванок Ж)
IMHO все таки стрельба по UDP он пошустрей будет чем TCP. Хотя может и ошибаюсь. Кстати интересно зачем использовать два протокола неужели UDP мало ?
Для стрельбы скорость передачи не важна, зато вожно, чтобы эти пакеты всегда доходили и не терялись по дороге. Поэтому для стрельбы используется TCP. А координаты самолетов передаются постоянно, если 1-2 пакета не дойдут - ничего страшного. Зато надо, чтоб они побыстрее доходили - меньше варпов и лагов будет. Соответственно - UDP.
Понятно толко в том же IL-2 повидимому хватает одного UDP для того и другого. Кстати не уточните кикие порты используются по UDP у AH ? Есче один плюс о котором я здесть говорил относительно UDP это то что для его работы не нужно создавать по потоку на клиента в отличии от TCP что сводит к нулю издержки на переключение контекство и синхронизацию при чтении общих данных. Хотя наверное и там можно без потоков интересно в WB это реализовано на потоках или без ?
Я не в курсе, что там в Ил2 делается. В любом случае, никто не утверждает, что нельзя только UDP использовать. Гвозди, например, можно и пассатижами забивать Там довольно много портов используется, какие точно - не знаю. Для TCP отдельные потоки тоже не обязательны. Просто это удобней программировать.
Из тех игрушек что видел большинство всяких action и т.п работают именно по UDP. Для игр где требуется минимальное время отклика это грабли IMHO. Если переключение контекстов в win это 18.2 раза в секунду. То при сотне другой подключений ждать пакет придется долго Для FTP это конечно пофиг особенно когда там пакеты забиты под завязку и довольно большие, а вот для игр где критично время ответа может статься что не очень. Хотя возможно я сгущаю краски все таки пакеты приходят не одновременно и винда вида переключается только на те потоки что не находятся в состоянии оидания. Пусть меня поправят более грамотные в этом товарищи
Нееее.... Народ, вы путаете стрельбу и дэмедж. UDP - протокол без гарантии доставки. Такчто когда в AH видешь как кон пуляет - это именно udp (User Datagram Protocol)... ты можешь этого и не увидеть, если пакет не дошёл. А вот поврежения, которые он тебе напулял, позиции самолеётов, чат - tcp.... и если у тебя таймаут tcp - то это уже диско. Не разу не играл в ИЛ2 (стыдно признаться ) но судя по описаниям - это обычный квейкоподобный сервер (только UDP) с интенсивным трафиком - нужен хороший канал (без потерь) - желательно лан, и небольшое (сравнивая с WB) количиество игроков.
Говорю тебе, как человек, у которого с 1.10 постоянно происходило переключение на TCP - координаты самолетов в АН изначально передаются по UDP. И если есть потери, то игра полностью переключается на TCP, т.е. вся инфа по нему начинает идти.