Winsock. send, recv по одному сокету из разных потоков.

Тема в разделе "WASM.NETWORKS", создана пользователем Span, 23 май 2008.

  1. Span

    Span New Member

    Публикаций:
    0
    Регистрация:
    5 ноя 2006
    Сообщения:
    134
    Уважаемые,

    Скажите, можно ли вообще с одним сокетом работать из разных потоков?
    Вернее не так. То что можно - я уже понял.
    Не будет ли логических ошибок при, например, одновременном вызове send двумя и более потоками? Пример: если я в одном потоке вызываю send, он начинает выполнение, тут другой поток тоже вызывает send. Как адресату придут данные? Сначала от первого вызова, а затем от второго? Или будет некая "вставка" данных? Сколько раз мне надо будет вызвать recv, чтобы получить все даные от 2х потоков клиента (буфер достаточно большой)?

    Еще пример: один поток заблокирован ф-ей recv, а тут другой поток вызвал send для того же сокета.

    Речь идет о блокирующих TCP сокетах. Хотя про UDP тоже интересно. Да и не только про winsock, но и про обычные бэркли.

    Как работать - не ясно. Копал MSDN - но четкого ответа не нашел.
     
  2. Aspire

    Aspire New Member

    Публикаций:
    0
    Регистрация:
    19 май 2007
    Сообщения:
    1.028
    Span
    Я бы перестраховался критическими секциями..
     
  3. nester7

    nester7 New Member

    Публикаций:
    0
    Регистрация:
    5 дек 2003
    Сообщения:
    720
    Адрес:
    Russia
    Будут. Нужна синхронизация.
     
  4. Span

    Span New Member

    Публикаций:
    0
    Регистрация:
    5 ноя 2006
    Сообщения:
    134
    Спасибо за ответы.

    Понял, одновременные вызовы send буду мьютексами защищать.

    А вот как быть, если один поток заблокирован вызовом recv, а другому надо вызвать send?
    Можно слать данные оставить? Или ждать, пока вернется recv?

    Пока я бы сделал так:
    1 сокет
    2 мьютекса

    первый защищает чтение, второй - запись.
    Так нормально?
     
  5. nester7

    nester7 New Member

    Публикаций:
    0
    Регистрация:
    5 дек 2003
    Сообщения:
    720
    Адрес:
    Russia
    Сокет имеет отделные буферы для отправки и приема. Пока recv ожидает данных в приемном буфере,
    можено делать send для буфера отправки.

    Ты лучше скажи, что ты хочешь сделать этими несколькими потоками и одним сокетом.

    А еще лучше, купи/скачай и почитай книгу "UNIX. Разработка сетевых приложений".
     
  6. Span

    Span New Member

    Публикаций:
    0
    Регистрация:
    5 ноя 2006
    Сообщения:
    134
    Спасибо.
    Да вот писал уже в одном топике, что хочу сделать приложение для отладки работы другого софта (клиент-сервер по TCP). Часто такие задачи бывают по работе. ПО встает в канал между клиентом и сервером. Логгирует траффик, измеряет задержки.
    Одним потоком читать и слать из 2х сокетов с помощью select у меня не получилось. Сделал в 2 потока на одно отлаживаемое соединение (2 сокета). Изначально после коннекта оба ждут в recv. Как только данные появились у одного из них - поток пишет в соответствующий сокет и логгирует все что написал.
    Вот меня и смущал факт работы 2х потоков с одним сокетом. Теперь стало ясно.
    Вопрос остался с accept. Если клиент делает connect на сервер, мое ПО сначала должно сделать accept клиента, а потом уже сделать connect на реальный сервер. Т.е. в любом случае клиенту удастся подключиться, даже если не поднят сервер. А это нарушает логику, и "отлаживанием" такой процесс уже нельзя назвать, т.к. в реале будет иначе. Вот как бы узнать, ждут меня на другом конце, или нет.

    По поводу "UNIX. Разработка сетевых приложений".
    Я пишу под винды. Слашал, что MS портировала сокеты Бэркли. Но все-равно вопрос остался: одинаково ли программирование сокетов (TCP, UDP, не raw) в UNIX и Windows?? + неясность вводит наличие у MS разных версий winsock.
     
  7. nester7

    nester7 New Member

    Публикаций:
    0
    Регистрация:
    5 дек 2003
    Сообщения:
    720
    Адрес:
    Russia
    Стопроцентно врят ли можно что-то сделать, но слёту два варианта есть:
    - в своем коде гонять в цикле connect/disconnect, обновляя флаг доступности сервера,
    который проверяешь при accept'e клентов.
    - однажды подключиться к серверу, настроив keepalive - если сервер станет недоступен,
    снова выставляем флаг, который проверяем при accept'e клентов.

    Базовые концепции одинаковы на всех осях, как-то: буферы для сокетов, поддерживаемые опции, структуры адресов и проч.
    Всё это, так или иначе, различается в реализации, но смысл и способ использования тот же.
     
  8. Span

    Span New Member

    Публикаций:
    0
    Регистрация:
    5 ноя 2006
    Сообщения:
    134
  9. nester7

    nester7 New Member

    Публикаций:
    0
    Регистрация:
    5 дек 2003
    Сообщения:
    720
    Адрес:
    Russia
    Еще вариант, пока что самый правильный:
    - как-то узнаем, что пришел клиент, но accept пока что не делаем (а-ля select).
    - делаем коннект к серверу.
    - если коннект есть, то делаем accept клиента, связываем сокеты и работает как нужно,
    если коннекта нет, то делаем accept клиента и сразу же закрываем его сокет.
     
  10. Span

    Span New Member

    Публикаций:
    0
    Регистрация:
    5 ноя 2006
    Сообщения:
    134
    Да, это действительно самый правильный вариант. Тогда ПО не нарушит логику работы.
    Вопрос теперь - как узнать что пришел клиент без accept(). Буду читать доки. Спасибо.
     
  11. nester7

    nester7 New Member

    Публикаций:
    0
    Регистрация:
    5 дек 2003
    Сообщения:
    720
    Адрес:
    Russia
    Можно банально и проще всего через select(). В книге что выше есть примеры и объяснения.

    Полистай еще Network Programming for Microsoft® Windows®, Second Edition. Тоже неплохая книга.
     
  12. nester7

    nester7 New Member

    Публикаций:
    0
    Регистрация:
    5 дек 2003
    Сообщения:
    720
    Адрес:
    Russia
    Если уж быть совсем точным и честным, то клиент подключится нормально до того как ты сделаешь accept().
    Подробнее почитай WASM.BEGINNERS.
     
  13. nester7

    nester7 New Member

    Публикаций:
    0
    Регистрация:
    5 дек 2003
    Сообщения:
    720
    Адрес:
    Russia
    А простыми tcpdump/wireshark нельзя? Размеры пакетов и временные интервалы они показывают - импортировать куда-нить и проанализировать.
     
  14. Span

    Span New Member

    Публикаций:
    0
    Регистрация:
    5 ноя 2006
    Сообщения:
    134
    Да можно, но не очень.
    Бывает что несколько экземпляров приложения работают. Причем каждое коннектится то к одному, то к другому серверу.
    Да и сам давно хотел уже написать какое-нибудь многопоточное приложение с использованием сокетов. Сколько можно то уже... Каждый раз в доки лезу.