Здравствуйте, ahaos, Вы писали:
A>Как это лучше организовать? Или вообще лучше сменить схемы ожидания и приема данных?
Я тебе советую не заниматься ковырянием сокетов, а взять высокоуровневую либу, например, gRPC, потратить один раз время на то, чтобы разобраться с ней, собрать и подключить к проекту после чего сфокусироваться на бизнес логике приложения, а не на технических деталях реализации транспорта своих данных.
Моя программа рассылает по сети сообщения. Удаленные компьютеры что-то делают и присылают результаты.
Нужно эти результаты принять.
На данный момент я хотел бы для каждого удаленного компьютера на принимающем хосте создать свой поток ожидания с функцией accept. Так и делаю.
Но функция accept срабатывает на все подряд и потокам нужно как-то отфильтровать под себя поступающие пакеты данных, т.е. конкретный поток ожидания должен принять данные только от конкретного удаленного компьютера.
Как это лучше организовать? Или вообще лучше сменить схемы ожидания и приема данных?
Здравствуйте, ahaos, Вы писали:
A>Моя программа рассылает по сети сообщения. Удаленные компьютеры что-то делают и присылают результаты. A>Нужно эти результаты принять.
A>На данный момент я хотел бы для каждого удаленного компьютера на принимающем хосте создать свой поток ожидания с функцией accept. Так и делаю.
Эээ кто на ком стоял, простите? О каком сетевом API речь?
В BSD sockets (которое скопировано в основах в винде) если UDP, там нет accept(), а если TCP или SCTP, то там... ну, конечно, можно сделать для каждого ремота свой слушающий порт, но зачем?
A>Но функция accept срабатывает на все подряд и потокам нужно как-то отфильтровать под себя поступающие пакеты данных, т.е. конкретный поток ожидания должен принять данные только от конкретного удаленного компьютера.
"Пакеты"? То есть UDP?
(вообще-то датаграммы, но "пакеты" тоже понятно)
Тогда где accept()? Или речь просто про recv()?
A>Как это лучше организовать? Или вообще лучше сменить схемы ожидания и приема данных?
Для начала в них разобраться, а то рассказ на уровне "нажимаю клаксон и машина съезжает на второстепенную".
Здравствуйте, ahaos, Вы писали:
N>>Для начала в них разобраться, а то рассказ на уровне "нажимаю клаксон и машина съезжает на второстепенную". A>Речь идет о Win32 Socket2. Используются блокированные сокеты, а также функции send, receive, bind, listen.
Правильно, это и есть BSD sockets (в отличие, например, от XTI sockets, где другие манеры, или ещё нескольких реализаций).
listen() — значит TCP, так? И создаёте по порту на каждый удалённый хост?
Или об установленном соединении? Какая сторона слушает, а какая коннектится к ней?
Здравствуйте, netch80, Вы писали:
N>Здравствуйте, ahaos, Вы писали:
N>>>Для начала в них разобраться, а то рассказ на уровне "нажимаю клаксон и машина съезжает на второстепенную". A>>Речь идет о Win32 Socket2. Используются блокированные сокеты, а также функции send, receive, bind, listen.
N>Правильно, это и есть BSD sockets (в отличие, например, от XTI sockets, где другие манеры, или ещё нескольких реализаций). N>listen() — значит TCP, так? И создаёте по порту на каждый удалённый хост? N>Или об установленном соединении? Какая сторона слушает, а какая коннектится к ней?
Нет. Я рассылаю задания удаленным машинам по сети. Далее запускаю сервер, который ждет от них результатов. Сервер слушает только один порт 888.
Поскольку я знаю скольким машинам я послал задание и их адреса, то я создаю на каждую машину свой поток ожидания в котором вызывается accept.
В идеале бы хотелось, что бы accept в своем потоке реагировала на конкретный IP-адрес, а остальные фильтровала, но она срабатывает на все что попало, что приходит на этот сервер. Я конечно проверяю с какого адреса пришло сообщение и если оно пришло с ненужного адреса, я опять в этом потоке возвращаюсь к функции accep и жду нового соединения. Но явно моя конструкция какая-то корявая и весь процесс рано или поздно на чем-то затыкается.
Может все таки нужно запустить один поток ожидания, а там уже разбираться с какой адрес установил соединение и предпринимать соответствующие действия?
Здравствуйте, ahaos, Вы писали:
A>Нет. Я рассылаю задания удаленным машинам по сети. Далее запускаю сервер, который ждет от них результатов. Сервер слушает только один порт 888. A>Поскольку я знаю скольким машинам я послал задание и их адреса, то я создаю на каждую машину свой поток ожидания в котором вызывается accept.
Таак. Если несколько тредов впараллель запускают accept() на одном слушающем сокете, то они внутри ядра, скорее всего, ставятся в очередь.
Когда придёт входящее соединение, его получит первый из вставших в очередь, следующее — второй, и так далее.
Хотя, может быть, это работает и в обратном порядке (слушание на IOCP, например, активирует последнего из вставших).
В любом случае тут чёткого маппинга, который хотите, не будет.
A>В идеале бы хотелось, что бы accept в своем потоке реагировала на конкретный IP-адрес, а остальные фильтровала, но она срабатывает на все что попало, что приходит на этот сервер. Я конечно проверяю с какого адреса пришло сообщение и если оно пришло с ненужного адреса, я опять в этом потоке возвращаюсь к функции accep и жду нового соединения.
Тогда просто теряете ответ, заставляя удалённую машину повторить его посылку (или потерять).
A> Но явно моя конструкция какая-то корявая и весь процесс рано или поздно на чем-то затыкается. A>Может все таки нужно запустить один поток ожидания, а там уже разбираться с какой адрес установил соединение и предпринимать соответствующие действия?
Да, можно и так — и это проще всего. Один тред слушает в accept(), на сокет определяет, от кого пришло, и порождает тред для отработки.
Контекст можно передать ему объектом в соответствии с адресом другого конца.
Альтернативно — таки на каждую удалённую машину порождать свой слушающий сокет. Но это хуже масштабируемо.
Здравствуйте, ahaos, Вы писали:
A>Моя программа рассылает по сети сообщения. Удаленные компьютеры что-то делают и присылают результаты. A>Нужно эти результаты принять.
A>На данный момент я хотел бы для каждого удаленного компьютера на принимающем хосте создать свой поток ожидания с функцией accept. Так и делаю.
A>Но функция accept срабатывает на все подряд и потокам нужно как-то отфильтровать под себя поступающие пакеты данных, т.е. конкретный поток ожидания должен принять данные только от конкретного удаленного компьютера. A>Как это лучше организовать? Или вообще лучше сменить схемы ожидания и приема данных?
Может вместе с заданием удалённым компам выдавать уникальные ключи (с сохранением этих ключей в мапу). Далее сделать один поток, ожидающий результаты, который проверяет ключ задания. Если ключ найден в мапе, то запускать поток обработки и ждать остальных результатов дальше. Иначе пропуск. Так-же можно учесть ситуацию, когда пришли все ответы.
Здравствуйте, ahaos, Вы писали:
A>явно моя конструкция какая-то корявая и весь процесс рано или поздно на чем-то затыкается.
Эт точно
A>Может все таки нужно запустить один поток ожидания, а там уже разбираться с какой адрес установил соединение и предпринимать соответствующие действия?