У меня есть событийно-ориентированная программа сетевого сервера. Эта программа принимает соединения от других процессов на других хостах. Может быть много недолгих соединений от различных портов на том же удаленном IP.
В настоящее время у меня есть a while(1)
цикл, который звонит accept()
и затем порождает поток для обработки нового соединения. Каждое соединение закрывается после того, как сообщение прочитано. На удаленном конце закрывается соединение после того, как сообщение отправляется.
Я хочу устранить издержки соединений установки и разъединения путем кэширования открытого сокета FDs. На стороне отправителя это легко - я просто не закрываю соединения и имею в наличии их.
На стороне получателя это немного более твердо. Я знаю, что могу сохранить FD, возвращенный accept()
в структуре и прислушиваются к сообщениям через все такое использование сокетов poll()
или select()
, но я хочу одновременно, оба прислушиваются к новым соединениям через accept()
и послушайте на всех кэшируемых соединениях.
Если я использую два потока, один на poll()
и один на accept()
, затем, когда accept()
назовите возвраты (новое соединение открыто), я должен разбудить другой поток, ожидающий на старом наборе соединений. Я знаю, что могу сделать это с сигналом и pselect()
, но эта целая путаница походит слишком на большую работу для чего-то настолько простого.
Существует ли вызов или превосходящая методология, которая позволит мне одновременно обработать новые открываемые соединения и данные, отправляемые на старых соединениях?
В прошлый раз, когда я проверял, вы могли просто прослушать
на сокете, а затем выбрать
или опрос
, чтобы узнать, есть ли соединение вошел. Если так, примите
его; он не будет блокироваться (но вы , возможно, захотите , на самом деле следует установить O_NONBLOCK, чтобы быть уверенным)
Я бы поместил слушателя в отдельный процесс (поток), чтобы не испортить ситуацию. И запустите рабочий процесс на другом для обработки существующих сокетов. На самом деле нет необходимости в неблокирующем слушателе. И никаких накладных расходов на потоки, выполняющих 2 потока.
Это должно работать следующим образом: вы принимаете поток слушателя до тех пор, пока он не вернет вам дескриптор клиентского сокета, и передадите его рабочему процессу, который выполняет на нем всю грязную работу чтения / записи.
Если вы хотите прослушивать несколько портов и не хотите удерживать один процесс для каждого прослушивателя, я предлагаю вам установить свой сокет в O_NONBLOCK и сделать что-нибудь вроде:
// loop through listeners here and poll'em for read, when read is successful call accept, get descriptor, pass it to worker and continue listen
while(1){
foreach( serverSocket in ServerSockets ){
if( serverSocket.Poll( 10, SelectRead ) ){
clientSocket = serverSocket.Accept();
// pass to worker here and release
}
}
}