winsock 2. потокобезопасность для одновременной отправки. ТСР - PullRequest
1 голос
/ 12 февраля 2010

возможно ли посылать несколько потоков по одному сокету? Будет ли чередование потоков или сокет будет блокироваться в первом потоке (при условии tcp)? кажется, что большинство мнений, которые я нашел, предостерегают от этого из-за очевидных опасений чередования, но я также нашел несколько комментариев, которые утверждают обратное. Являются ли чередование страхов переносом winsock1 и являются ли они обоснованными для winsock2? Есть ли способ установить сокет winsock2, который позволит отсутствие локальной синхронизации?

два противоположных мнения ниже ... кто прав?

комментарий 1

"Реализация Winsock 2 должна быть полностью поточно-ориентированной. Одновременное чтение / запись в разных потоках должно завершаться успешно или завершаться неудачно с WSAEINPROGRESS, в зависимости от установки флага перекрытия при создании сокета. В любом случае по умолчанию создаются перекрывающиеся сокеты ; так что вам не нужно об этом беспокоиться. Убедитесь, что вы не используете NT SP6, если вы используете SP6a, у вас должно быть все в порядке! "

источник

комментарий 2

"Одна и та же DLL не доступна нескольким процессам с момента появления Windows 95. Каждый процесс получает свою собственную копию доступного для записи сегмента данных для DLL. Модель" все процессы общего доступа "была старой моделью Win16 , который, к счастью, совершенно мертв и похоронен ;-) "

источник

с нетерпением жду ваших комментариев! джим

~ edit1 ~ чтобы уточнить, что я имею в виду под чередованием. Поток 1 отправляет сообщение «Hello». Поток 2 отправляет сообщение «world!». Получатель получает: «Hwoel Lorld!». это предполагает, что оба сообщения НЕ были отправлены в цикле while. Это возможно?

Ответы [ 2 ]

2 голосов
/ 12 февраля 2010

Я бы действительно советовал не делать этого в любом случае. Функции отправки могут отправлять меньше, чем вы говорите, по различным вполне законным причинам, и если другой поток может войти и попытаться также что-то отправить, вы просто испортите свои данные.

Теперь вы, конечно, можете записывать в сокет из нескольких потоков, но у вас больше нет контроля над тем, что происходит на проводе, если вы не правильно заблокировали на уровне приложения.

рассмотрите возможность отправки некоторых данных:

WSASend(sock,buf,buflen,&sent,0,0,0:

параметр sent будет содержать номер. фактически отправленных байтов - аналогично возвращаемому значению функции send(). Чтобы отправить все данные в buf, вам придется выполнить цикл WSASend, пока все все данные не будут отправлены.

Если, скажем, первый WSASend отправляет все, кроме последних 4 байтов, другой поток может пойти и отправить что-то, пока вы возвращаетесь назад и пытаетесь отправить последние 4 байта.

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

1 голос
/ 12 февраля 2010

возможно ли посылать несколько потоков по одному сокету?

Да - хотя, в зависимости от реализации это может быть больше или меньше видимым. Сначала я уточню, откуда я иду:

  1. C # / .Net 3.5
  2. System.Net.Sockets.Socket

Общая видимость (т. Е. Требуемое управление) потоков и возникших головных болей будет напрямую зависеть от того, как реализован сокет (синхронно или асинхронно). Если вы идете по синхронному маршруту, то у вас много работы по ручному управлению подключением, отправкой и получением через несколько потоков. Я настоятельно рекомендую избегать этой реализации. Усилия по правильному и эффективному выполнению синхронных методов в поточной модели просто не стоят сравнимых усилий по реализации асинхронных методов.

Я реализовал асинхронный Tcp-сервер за меньшее время, чем мне потребовалось для реализации многопоточной синхронной версии. Async намного легче отладить - и если вы намерены использовать Tcp (мой любимый выбор), у вас действительно мало забот о потерянных сообщениях, пропущенных данных или чем-то еще.

будет ли чередование потоков или будет ли сокет блокироваться в первом потоке (при условии tcp)?

Мне пришлось исследовать чередующиеся потоки (из вики), чтобы убедиться, что я правильно понял то, что вы спрашиваете. Чтобы лучше понять чередование и смешанные сообщения , обратитесь к этим ссылкам в вики:

  1. Протокол обмена сообщениями в реальном времени
  2. Протокол управления передачей

В частности, мощность Tcp лучше всего описана в следующем разделе:

Из-за перегрузки сети, балансировки нагрузки на трафик или другого непредсказуемого поведения сети, IP-пакеты могут быть потерян, продублирован или доставлен из строя. TCP обнаруживает эти проблемы, запрашивает повторную передачу потерянного пакеты, переупорядочивает неупорядоченные пакеты и даже помогает минимизировать перегрузку сети, чтобы уменьшить возникновение других проблем. Как только приемник TCP наконец собрал идеальную копию данных первоначально переданный, он передает эту дейтаграмму в прикладную программу. Таким образом, TCP абстрагирует приложение связь из основных сетевых деталей.

Это означает, что чередующиеся сообщения будут переупорядочены в соответствующие им сообщения , отправленные отправителем. Ожидается, что многопоточность участвует или будет участвовать в разработке механизма клиент-сервер Tcp, ориентированного на производительность - будь то с помощью асинхронных или синхронизирующих методов.

Чтобы сокет не блокировался, вы можете установить для его свойства Blocking значение false.

Надеюсь, это даст вам хорошую информацию для работы. Черт, я даже немного научился ...

...