C ++ Sockets Send () Потокобезопасность - PullRequest
4 голосов
/ 13 июля 2010

Я кодирую сервер сокетов максимум на 1000 клиентов, сервер о моей игре, я использую неблокирующие сокеты и около 10 потоков, которые получают данные одновременно из разных сокетов (первый поток получает от 0 до 100, второй от 101-200 и тд ..)

но если поток 1 хочет отправить данные всем 1000 клиентам, а поток 2 также хочет отправить данные всем 1000 клиентам одновременно, это безопасно? есть ли вероятность того, что данные будут испорчены на другой (клиентской) стороне?

если да, я думаю, единственная проблема, которая может произойти, это то, что иногда клиент получит 2 или 10 пакетов как 1 пакет, это правильно? если да, есть ли какое-либо решение для этого: (

Ответы [ 4 ]

2 голосов
/ 16 июля 2010

Обычная схема работы со многими сокетами - выделение отдельного потока для событий ввода / вывода с select(2), poll(2) или лучше kqueue(2) или epoll(4) (в зависимости от платформы), действующий в качестве диспетчера событий сокета. Сокеты обычно обрабатываются в неблокирующем режиме. Тогда можно создать пул потоков, реагирующих на события, и либо выполнять чтение и запись напрямую, либо через буферы / очереди более низкого уровня.

Здесь применимы всевозможные методы - от очередей до досок подписки на события Это становится сложным с мультиплексированием принимает / читает / пишет / EOFs на уровне ввода-вывода и с арбитражем событий на уровне приложения. Несколько библиотек, таких как <b>libevent</b> и <b>boost::asio</b>, помогают структурировать нижний уровень (библиотека ACE также находится в этом пространстве, но я не хотел бы рекомендовать его никому). Вам придется самостоятельно придумывать протоколы уровня приложений и конечные автоматы (опять же, <b>boost::statechart</b> может помочь).

Несколько хороших ссылок, чтобы лучше понять, с чем вы столкнулись (это, вероятно, миллионный раз, когда они упоминаются здесь на SO):

Извинения за то, что не предлагали конкретного решения, но это очень широкий вопрос проектирования, и большинство решений сильно зависят от контекста (хотя это очень весело). Надеюсь, это немного поможет.

1 голос
/ 13 июля 2010

Поскольку вы отправляете данные с использованием разных сокетов, проблем не должно быть. Скорее, когда эти разные потоки обращаются к одним и тем же данным, вы должны обеспечить целостность данных.

0 голосов
/ 14 июля 2010

Вы используете сокеты UDP или TCP?

Если UDP, каждая запись должна быть инкапсулирована в отдельный пакет и перенесена на другую сторону без изменений. Порядок можно поменять местами (как и для любого UDP-пакета), но они должны быть целыми.

Если TCP, на транспортном уровне нет концепции пакетов, и любые 10 записей на одной стороне могут быть объединены на другой стороне в одном чтении. Записи TCP также могут принимать только часть вашего буфера, поэтому даже если функция send () является атомарной, ваша запись не обязательна. В этом случае вам нужно синхронизировать его.

0 голосов
/ 13 июля 2010

send () не является атомарным в большинстве реализаций, поэтому отправка 1000 различных сокетов из нескольких потоков может привести к тому, что на стороне клиента появятся смешанные сообщения, и возникнут различные странности.(Я ничего не знаю, см. Комментарии Николая и Роберта ниже, но остальная часть моего комментария все еще остается в силе (с точки зрения решения вашей проблемы))

Я бы использовал потоки для отправкиВы используете их для получения.Один поток для управления отправкой в ​​один (или несколько) сокетов, который гарантирует, что вы не будете писать в один сокет из нескольких потоков одновременно.

Также посмотрите здесь для некоторого дополнительного обсужденияи более интересные ссылки.Если вы работаете в Windows, программисты winsock faq являются бесценным ресурсом, для вашей проблемы см. здесь .

...