Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > Прием и передача мультикастовых сообщений.


Автор: GL_basik 20.12.2006, 17:58
Теоритически возможно передавать и принимать мультикастовые сообщения через один и тот же сокет. Я сделал обычный сокет, настроил его для работы по мультикасту. Теперь столкнулся с проблемой. Если я даю команду на прием сообщения, то выполнение программы останавливается и ожидает пока что-нибудь придет. А мне необходимо чтоб выполнение программы не останавливалось. И, если ничего не пришло, снова шла передача. Как можно решить данную задачу?
Да привожу пример кода:

Код

  //описание переменных 
  int iOptVal = 64;
  char RecvBuf[1024];

  TCHAR szError[100];                          // Error message string
  SOCKET Sock = INVALID_SOCKET;     // Datagram window socket


  struct ip_mreq mreq;                          // Used in adding or dropping
                                                             // multicasting addresses

  SOCKADDR_IN source_sin,                 // Source socket address
                          dest_sin;                    // Destination socket address

  WSADATA WSAData;                           // Contains details of the
                                                             // Winsock implementation

  // Initialize Winsock
  char iResult = WSAStartup(MAKEWORD(2,2), &WSAData);
  if (iResult != 0)
  {
    ShowMessage("Ñåòü íå ðàáîòàåò");
    return;
  }

  //создаем сокет
  if ((Sock = socket (AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
  {
    ShowMessage("Allocating socket failed!");
    return;
  }

  //источник
  source_sin.sin_family = AF_INET;
  source_sin.sin_port = htons (SOURCE_PORT);
  source_sin.sin_addr.s_addr = htonl (INADDR_ANY);

  // Associate the source socket's address with the socket, Sock.
  if (bind (Sock, (struct sockaddr FAR *) &source_sin,
            sizeof (source_sin)) == SOCKET_ERROR)
  {
    ShowMessage("Binding socket failed!");
    closesocket (Sock);
    return;
  }
  //время жизни пакетов TTL
  if (setsockopt (Sock,
                  IPPROTO_IP,
                  IP_MULTICAST_TTL,
                  (char FAR *)&iOptVal,
                  sizeof (int)) == SOCKET_ERROR)
  {
    ShowMessage("setsockopt failed!");
    closesocket (Sock);
    return;
  }

  // Join the multicast group from which to receive datagrams.
  mreq.imr_multiaddr.s_addr = inet_addr (DEST_MCAST);
  mreq.imr_interface.s_addr = INADDR_ANY;
  if (setsockopt (Sock,
                  IPPROTO_IP,
                  IP_ADD_MEMBERSHIP,
                  (char FAR *)&mreq,
                  sizeof (mreq)) == SOCKET_ERROR)
  {
    ShowMessage("setsockopt failed!");
    closesocket (Sock);
    return;
  }

  //мультикастовая группа
  dest_sin.sin_family = AF_INET;
  dest_sin.sin_port = htons (DESTINATION_PORT);
  dest_sin.sin_addr.s_addr = inet_addr (DEST_MCAST);

  int iRecvLen = sizeof (source_sin);

  do //собственно принимаем и передаем, пока поток не остановлен
  {
    if (Form1->Multi_Param.send_flag)
    {
      Form1->Multi_Param.send_flag=false;
      // Send a message to the multicasting address.
      if (sendto (Sock,
                  Form1->Multi_Param.multi_mess,
                  strlen (Form1->Multi_Param.multi_mess),
                  0,
                  (struct sockaddr FAR *) &dest_sin,
                  sizeof (dest_sin)) == SOCKET_ERROR)
      {
        ShowMessage("sendto failed!");
        closesocket (Sock);
        return;
      }
    }
    else
    {
      // Receive data from the multicasting group server.
//Вот здесь программа останавливается и ждет пока придет сообщение!!!
      int Errnum=recvfrom (Sock,
                           RecvBuf,
                           100,
                           0,
                           (struct sockaddr FAR *) &source_sin,
                           &iRecvLen);
      if (Errnum == SOCKET_ERROR)
      {
        ShowMessage("recvfrom failed!");
        closesocket (Sock);
        return;
      }
    }
  }
  while (!Terminated); //óáèëè ïðèëîæåíèå Æ-(
  // Disable sending on Sock before closing it.
  shutdown (Sock, 0x01);
  // Close Sock.
  closesocket (Sock);
  WSACleanup();

Автор: GL_basik 21.12.2006, 16:25
Что никто ничего не посоветует?
Видимо придется организовывать еще один поток и настроить там асинхронный сокет на прием.... 

Автор: dumb 22.12.2006, 02:46
Цитата(GL_basik @  21.12.2006,  16:25 Найти цитируемый пост)
еще один поток и настроить там асинхронный сокет

масло масляное.

в "еще одном потоке" можно уже обычный блокирующий сокет делать.
либо твой изначальный сокет сделать неблокирующим.
и еще кучка вариантов...

Автор: GL_basik 22.12.2006, 10:10
dumb, я, по-моему, и спрашивал как 
Цитата(dumb @  22.12.2006,  02:46 Найти цитируемый пост)
изначальный сокет сделать неблокирующим.

но что-то никто не ответил....

Автор: dumb 22.12.2006, 18:08
GL_basik, есть такое чУдное средство - поиск.

Код

int value = 1;
ioctlsocket( sock, FIONBIO, &value);


при этом немного меняется схема работы с сокетом, так что советую воспользоваться таки поиском: инфы и примеров - море.

Автор: GL_basik 25.12.2006, 11:04
dumb, Спасибо за подсказку, теперь я знаю в каком напрвлении искать.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)