title: can not recv any multicast data on winsock in cpp
body: <pre class="lang-cpp prettyprint-override"><code>#include &lt;winsock2.h&gt;
  #include &lt;ws2tcpip.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;iostream&gt;
  #define MCASTADDR &quot;233.0.0.1&quot; //本例使用的多播组地址。
  #define MCASTPORT 5150 //绑定的本地端口号。
  #define BUFSIZE 1024 //接收数据缓冲大小。
  #pragma comment(lib,&quot;ws2_32&quot;)
  int main( int argc,char ** argv) {
      WSADATA wsd;
      struct sockaddr_in local,remote,from;
      SOCKET sock,sockM;
      TCHAR recvbuf[BUFSIZE];
      /*struct ip_mreq mcast; // Winsock1.0 */
      int len = sizeof( struct sockaddr_in);
      int ret;
  //初始化 WinSock2.2
      if( WSAStartup( MAKEWORD(2,2),&amp;wsd) != 0 ) {
          printf(&quot;WSAStartup() failed\n&quot;);
          return -1;
      }
      /*
      创建一个 SOCK_DGRAM 类型的 SOCKET
      其中,WSA_FLAG_MULTIPOINT_C_LEAF 表示 IP 多播在控制面层上属于
      &quot;无根&quot;类型;
      WSA_FLAG_MULTIPOINT_D_LEAF 表示 IP 多播在数据面层上属于&quot;无根&quot;,
      有关控制面层和
      数据面层有关概念请参阅 MSDN 说明。
      */
      if((sock=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,
                         WSA_FLAG_MULTIPOINT_C_LEAF|WSA_FLAG_MULTIPOINT_D_LEAF|
                         WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) {
          printf(&quot;socket failed with:%d\n&quot;,WSAGetLastError());
          WSACleanup();
          return -1;
      }
      int enable = 1;
      setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&amp;enable, sizeof(int));
  //将 sock 绑定到本机某端口上。
      local.sin_family = AF_INET;
      local.sin_port = htons(MCASTPORT);
  //    local.sin_addr.s_addr = INADDR_ANY;
      local.sin_addr.s_addr = inet_addr(&quot;10.1.12.74&quot;);
      if( bind(sock,(struct sockaddr*)&amp;local,sizeof(local)) == SOCKET_ERROR ) {
          printf( &quot;bind failed with:%d \n&quot;,WSAGetLastError());
          closesocket(sock);
          WSACleanup();
          return -1;
      }
  //加入多播组
      remote.sin_family = AF_INET;
      remote.sin_port = htons(MCASTPORT);
      remote.sin_addr.s_addr = inet_addr( MCASTADDR );
      /* Winsock1.0 */
      /*
      mcast.imr_multiaddr.s_addr = inet_addr(MCASTADDR);
      mcast.imr_interface.s_addr = INADDR_ANY;
      if( setsockopt(sockM,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char*)&amp;mcast,
      sizeof(mcast)) == SOCKET_ERROR)
      {
      printf(&quot;setsockopt(IP_ADD_MEMBERSHIP) failed:%d\n&quot;,WSAGetLastError());
      closesocket(sockM);
      WSACleanup();
      return -1;
      }
      */
      /* Winsock2.0*/
      if(( sockM = WSAJoinLeaf(sock,(SOCKADDR*)&amp;remote,sizeof(remote),
                               NULL,NULL,NULL,NULL,
                               JL_BOTH)) == INVALID_SOCKET) {
          printf(&quot;WSAJoinLeaf() failed:%d\n&quot;,WSAGetLastError());
          closesocket(sock);
          WSACleanup();
          return -1;
      }
  //接收多播数据,当接收到的数据为&quot;QUIT&quot;时退出。
      std::cout &lt;&lt; WSAGetLastError() &lt;&lt; std::endl;
      while(true) {
          if(( ret = recvfrom(sock,recvbuf,BUFSIZE,0,
                              (struct sockaddr*)&amp;from,&amp;len)) == SOCKET_ERROR) {
  
              printf(&quot;recvfrom failed with:%d\n&quot;,WSAGetLastError());
              closesocket(sockM);
              closesocket(sock);
              WSACleanup();
              return -1;
  
          }
  
          if( strcmp(recvbuf,&quot;QUIT&quot;) == 0 ) break;
          else {
              recvbuf[ret] = '\0';
              printf(&quot;RECV:' %s ' FROM &lt;%s&gt; \n&quot;,recvbuf,inet_ntoa(from.sin_addr));
          }
      }
      closesocket(sockM);
      closesocket(sock);
      WSACleanup();
      return 0;
  }
  </code></pre>
  <p>i hava tried use python to recv data,and it successed. no way can I recv any multicast data.
  in some cast, I can recv a winerror 10014.I really dont know how to fix it. and I dont know what does this happend.</p>
  <p>I use the tdm-gcc 10</p>
  <p>in other computer use the dev-cpp can recv the data in the same code above(it's ip is 10.1.12.88).and it recv data sended by me.</p>
  <p>can someone tell me what the reason is.</p>
  <p>the python code are like this:</p>
  <pre class="lang-py prettyprint-override"><code>import logging
  from socket import *
  from threading import Thread
  
  logging.basicConfig(level=logging.INFO)
  
  
  def handleSend(client, multicast_address, multicast_port):
      while True:
          in_data = input(&quot;请输入你的消息:&quot;).encode()
          r = client.sendto(in_data, (multicast_address, multicast_port))
          logging.info(f&quot;send status is {r}&quot;)
  
  
  def handleReceive(client):
      while True:
          out_data, send_address = client.recvfrom(1024)
          print(f&quot;{send_address}: &quot;, out_data.decode())
          logging.info(f&quot;从{send_address}接收到数据&quot;)
  
  
  def app():
      address = '10.1.12.74'
      # address = '0.0.0.0'
      # address = '192.168.1.104'
      multicast_address = '233.0.0.1'
      multicast_port = 5150
      client = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)  # 创建UDP socket
      client.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)  # 允许端口复用
      client.bind((address, multicast_port))  # 绑定监听多播数据包的端口
      # client.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)  # 不一定需要，让套接字可以被多个程序使用，而不是独占端口
      # client.setsockopt(IPPROTO_IP, IP_MULTICAST_TTL, 255)  # 告诉内核这是一个多播类型的socket
      client.setsockopt(IPPROTO_IP,  # 告诉内核把自己加入指定的多播组，组地址由第三个参数指定
                        IP_ADD_MEMBERSHIP,
                        inet_aton(multicast_address) + inet_aton(address))
  
      try:
          Thread(target=handleReceive, args=(client,)).start()
          Thread(target=handleSend, args=(client, multicast_address, multicast_port)).start()
      except KeyboardInterrupt as e:
          logging.fatal(e)
          client.close()
  
  
  def createSocket():
      client = socket(AF_INET, SOCK_DGRAM)
      return client
  
  
  #
  if __name__ == '__main__':
      app()
  
  </code></pre>
  <p>I have also a code act both sender and recver in cpp like this:</p>
  <pre class="lang-cpp prettyprint-override"><code>#include &lt;winsock2.h&gt;
  #include &lt;ws2tcpip.h&gt;
  #include &lt;mswsock.h&gt;
  #include &lt;iostream&gt;
  #include &lt;cstdint&gt;
  
  namespace net {
      void init() {
          static bool condition = true; //
          if (condition) {
              WSADATA wsaData;
              // 初始化win sock2
              auto r = WSAStartup(MAKEWORD(2, 2), &amp;wsaData);
              if (r != 0) {
                  printf(&quot;初始化失败，错误代码 %d\n&quot;, r);
                  exit(-3);
              }
              puts(&quot;初始化成功!&quot;);
          }
          condition = false;
      }
  
      [[maybe_unused]] void finished() {
          static bool condition = true; //
          if (condition) {
              WSACleanup();
              puts(&quot;cleanup successes!&quot;);
          }
          condition = false;
      }
  
      SOCKET dialTCP(sockaddr_in *address) {
          init();
          auto client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
          if (client &lt; 0) {
              printf(&quot;failure create socket %d&quot;, client);
              exit(-3);
          }
          auto r = connect(client, (sockaddr *) address, sizeof(sockaddr_in));
          if (r != 0) {
              printf(&quot;Failure on connecting %d&quot;, r);
              exit(-3);
          }
          return client;
      }
  }
  
  /* OUT: whatever setsockopt() returns */
  int join_source_group(SOCKET socket,uint32_t grpaddr, uint32_t srcaddr, uint32_t iaddr) {
      ip_mreq_source imr{};
      imr.imr_multiaddr.s_addr = grpaddr;
      imr.imr_sourceaddr.s_addr = srcaddr;
      imr.imr_interface.s_addr = iaddr;
      return setsockopt(socket, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP, (char *) &amp;imr, sizeof(imr));
  }
  
  int leave_source_group(int sd, uint32_t grpaddr, uint32_t srcaddr, uint32_t iaddr) {
      ip_mreq_source imr{};
      imr.imr_multiaddr.s_addr = grpaddr;
      imr.imr_sourceaddr.s_addr = srcaddr;
      imr.imr_interface.s_addr = iaddr;
      return setsockopt(sd, IPPROTO_IP, IP_DROP_SOURCE_MEMBERSHIP, (char *) &amp;imr, sizeof(imr));
  }
  
  int main() {
      net::init();
      auto the_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  
      sockaddr_in service = net::makeAddress(&quot;10.1.12.74&quot;, 5150);
  
  
  
      int ret = bind(the_socket, (SOCKADDR *) &amp;service, sizeof(service));
  
      unsigned int grpaddr = inet_addr(&quot;233.0.0.1&quot;);
      unsigned int iaddr = inet_addr(&quot;10.1.12.74&quot;);
  
  //You should have the equivalent function in your existing client
  //to join the multicast group
  //    ret = join_source_group(the_socket, grpaddr, service.sin_addr.s_addr, iaddr);
  //    std::cout &lt;&lt;&quot;join to group returns&quot;&lt;&lt; ret &lt;&lt; std::endl;
  //
  
      std::string data = &quot;为啥你自己收不到数据,给点作用,我真的是无语了,？？？？？？？？？？？？？？？？&quot;;
  
      sockaddr_in group = net::makeAddress(&quot;233.0.0.1&quot;, 5150);
  
  
      auto r = WSAJoinLeaf(the_socket, reinterpret_cast&lt;SOCKADDR *&gt;(&amp;group), sizeof(group), nullptr, nullptr, nullptr,
                           nullptr,
                           JL_BOTH);
      std::cout &lt;&lt; &quot;join returns &quot; &lt;&lt; r &lt;&lt; std::endl;
      ret = sendto(the_socket, data.c_str(), data.length(), 0, (const sockaddr *) &amp;group, sizeof(group));
      std::cout &lt;&lt; &quot;send bytes&quot; &lt;&lt; ret &lt;&lt; std::endl;
  
      std::array&lt;char, 1024&gt; buf{};
  //    ret = recv(the_socket, buf.data(), buf.max_size(), 0);
  
      std::cout &lt;&lt; WSAGetLastError() &lt;&lt; std::endl;
      int len = sizeof(buf);
      if ((ret = recvfrom(the_socket, buf.data(), buf.max_size(), 0, (struct sockaddr *) &amp;group, &amp;len)) == SOCKET_ERROR) {
          printf(&quot;recv from failed with:%d\n&quot;, WSAGetLastError());
          WSACleanup();
          return -1;
      }
      buf[ret] = '\0';
      printf(&quot;RECV:' %s ' FROM &lt;%s&gt; \n&quot;, buf.data(), inet_ntoa(group.sin_addr));
  
  
      std::cout &lt;&lt; &quot;recv bytes&quot; &lt;&lt; ret &lt;&lt;
                std::endl;
      leave_source_group(the_socket, grpaddr, service
              .sin_addr.s_addr, iaddr);
      return 0;
  }
  
  
  </code></pre>