Работа с одним сокетом из нескольких потоков (трабл)

Тема в разделе "WASM.NETWORKS", создана пользователем Bohdan200, 5 окт 2006.

  1. Bohdan200

    Bohdan200 New Member

    Публикаций:
    0
    Регистрация:
    13 сен 2005
    Сообщения:
    134
    Адрес:
    Lviv
    Написал DLL, одна из ее функций создает блокирующий UDP сокет, после чего создает еще один поток. Причем с одним и тем же сокетом (именно с тем же значением хендла сокета) работает как основной поток(только на передачу), так и второй, созданный той функцией DLL(только на прием). Наблюдаю сташные глюки, пакеты регулярно дублируются, у меня есть подозрение что система создала два отдельных буфера для обеих потоков, хотя я работаю с одним и тем же сокетом. Порыл МСДН и гугл, ничего толкового не нашел. Разясните плис, это я просто страшно криво все зделал и так делать нельзя, или...
    Код потока выкладываю, он маленький
    Код (Text):
    1. DWORD WINAPI RecvThread(LPVOID lpParameter)
    2. {
    3.     sockaddr_in DevAddr;
    4.     CMD_HDR     CHeader;
    5.     int         DevAddrLn;
    6.     int         DevID;
    7.  
    8.     do {
    9.         DevAddrLn = sizeof(sockaddr_in);
    10.         recvfrom(hSocket, (char*)&CHeader, sizeof(CMD_HDR), 0, (sockaddr*)&DevAddr, &DevAddrLn);
    11.         DevID = DeviceByDevIP(&DevAddr);
    12.         if(DevID>=0)
    13.         {
    14.             switch(CHeader.Command) {
    15.                     case COM_ROLLING_STOP|128:
    16.                         SetEvent(Devices[DevID]->hEvntSTOP);
    17.                         outstr("Recieved STOP\n");
    18.                         break;
    19.  
    20.                     case COM_ROLLING_LOAD|128:
    21.                         SetEvent(Devices[DevID]->hEvntLOAD);
    22.                         outstr("Recieved LOAD\n");
    23.                         break;
    24.  
    25.                     case COM_ROLLING_PLAY|128:
    26.                         SetEvent(Devices[DevID]->hEvntPLAY);
    27.                         outstr("Recieved PLAY\n");
    28.                         break;
    29.  
    30.                     case COM_ROLLING_PLAYNEXT|128:
    31.                         SetEvent(Devices[DevID]->hEvntPLAYNEXT);
    32.                         outstr("Recieved PLAYNEXT\n");
    33.                         break;
    34.  
    35.                     case COM_ROLLING_PARAM|128:
    36.                         SetEvent(Devices[DevID]->hEvntPARAM);
    37.                         outstr("Recieved PARAM\n");
    38.                         break;
    39.  
    40.                     case COM_ROLLING_DISCONNECT|128:
    41.                         SetEvent(Devices[DevID]->hEvntDISCONNECT);
    42.                         outstr("Recieved DISCONNECT\n");
    43.                         break;
    44.             }
    45.         }
    46.     } while(WSAGetLastError() == 0);
    47.     return 0;
    48. };
    Как видно, тут только прием. А в основном потоке - только передача + WaitForSingleObject описаных выше Event-ов.

    З.Ы. Прога работает с несколькими самопальными дэвайсами которые сидят на Ethernet-e, причем их прошивка ОК, так как с однопоточной версией DLL все нормально. Но однопоточная DLL может работать только с 1 дэвайсом, а согласно поставленной задаче их может быть до 10
     
  2. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Почему бы не не работать создавать отдельное подключение на каждый девайс?
     
  3. Bohdan200

    Bohdan200 New Member

    Публикаций:
    0
    Регистрация:
    13 сен 2005
    Сообщения:
    134
    Адрес:
    Lviv
    Может я туплю, но дэвайсы по UDP работают, понятия "соединение" нет. Я просто создаю socket а потом делаю bind на 30303 порт, после чего этот сокет хавает пакеты на этот порт от ВСЕХ устройств, хотя IР у них разные. Узнать от кого пакет можно только в recvfrom().
     
  4. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Пардон, невнимательно прочёл.
     
  5. TheRawGod

    TheRawGod New Member

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

    А вот что касается дублирования, я когда-то столкнулся с похожим. У натогда в локальной сети процентов 75 удп пакетов дублировалось, а процентов 10 так и не доходило в случае определенной связки клиент-сервер.
    В том случае ситуация оказалось связанной с наличием на принимающей тачке нескольких сетевых интерфейсов, в т.ч. и виртуальных.
    Вылечилось танцами с бубном, а именно отключением ненужного физического интерфейса и отказом от одного виртуального, вроде так было. А кроме того долечилось усовершенствованием протокола передачи, для защиты от таких случаев:)

    С другой стороны - удп, он и есть удп, и жаловаться тут нечего:)
     
  6. Bohdan200

    Bohdan200 New Member

    Публикаций:
    0
    Регистрация:
    13 сен 2005
    Сообщения:
    134
    Адрес:
    Lviv
    TheRawGod
    Да, у меня предусмотрен тот случай, что удп пакеты могут терятся, приходить не в том порядке, дублироватся и т.п. но это все в будущем. А сейчас испытательный вариант - прямой коннект машина - устройство, т.е. никто больше не мешает. Че за хрень не могу понять... Уже третий день бюсь головой о клавиатуру!
    Когда разрабатывался девайс как раз так и предполагали, а тут... Чувствую жучку искать долго придется :dntknw: