- Как создать постоянное соединение с сервером <-> Client, как описано выше.
У вас есть несколько вариантов: вы можете написать многопоточноесервер, где один «процесс» с большей частью совместно используемой памяти выполняет несколько потоков выполнения, и каждый поток имеет некоторое локальное хранилище потока, например, client
.Или вы могли бы написать многопроцессорный сервер, где каждое клиентское соединение получает свой собственный независимый процесс через fork(2)
(что в значительной степени означает, что оно работает только на Unix, так как Windows пытается реализовать fork(2)
никогда не работает хорошо).Или вы можете написать конечный автомат на основе цикла событий и использовать select(2)
или poll(2)
или epoll(4)
для управления тем, какие клиенты доступны для чтения, записи и имеют ошибки.
Выбор между ними может показатьсясложно, но есть рекомендации .Я хотел бы предположить, что -small- системы, где ожидается, что у вас будет только 20-30 одновременных клиентов, могут быть очень хорошо обработаны через многопоточные или разветвленные серверы.Если вы хотите выйти за пределы этого числа одновременных клиентов, вы должны использовать такой инструмент, как EventMachine или libevent , чтобы написать свой сервер.(Который может быть, а может и не быть проще поддерживать.)
2) Есть ли лучший способ сохранить сервер открытым без использования цикла [потому что я чувствую, что совершил убийство, создаваябесконечный цикл]
Бесконечные циклы вполне хороши :), но иногда имеет смысл предложить способ перезапустить серверы или завершить их с помощью signal(7)
s или специализированных командных интерфейсов.
3) Почему он так приостановлен без client.close на сервере?Сервер буферизует сообщения перед отправкой?
Ах, здесь - вопрос, который вам действительно нужен - TCP попытается буферизовать результатынескольких пакетов с сервера, и из-за потенциальной необходимости фрагментации слишком больших пакетов в середине маршрута вы, как клиент, не имеете никаких гарантий о сохранении любых границ дейтаграмм.
Скорее всего, очень хорошо, что стек TCP / IP вашего сервера немного подождал, прежде чем отправлять первый пакет, чтобы узнать, скоро ли поступит больше данных.(Часто так и бывает.) Вероятно, он объединил два вызова client.print()
в один пакет TCP.Ваш клиент вызывает client.read()
дважды , но, вероятно, данных достаточно только для чтения one .Если вы хотите, чтобы ваш поток TCP отправлял первый пакет немедленно , вы можете установить параметр сокета TCP_NODELAY
, чтобы отключить эту небольшую задержку.(Но это может не помочь всем само по себе; вам может понадобиться использовать его вместе с TCP_CORK
, чтобы попытаться «заморозить» все записи, пока вы не очистите их явно. Это, вероятно, ужасная идея.)
Лучшим вариантом было бы переписать ваш клиент, чтобы он знал о протоколе между вашим сервером и клиентом;ему нужно прочитать входные данные в буфер, проанализировать буфер, чтобы найти «полные сообщения», использовать эти сообщения, а затем вернуться в свой основной цикл обработки событий.
Возможно, ваш протокол предназначен для чтения / записи ASCII или UTF-8 оканчивается "\n"
символами;в этом случае вы можете изменить print
на puts
или добавить \n
в нужных местах и изменить read()
на readline()
.(Это позволит стандартной библиотеке ввода-вывода обрабатывать ваш протокол для вас.) Другой подход заключается в отправке данных с длинами + пары данных и ожидании правильной длины данных.