菜鸟向高手学习 2019-05-26 12:01 采纳率: 0%
浏览 418
已结题

X86与X64两种平台,实现组播功能,X86的组播接收正常,X64的组播接收不正常。

编译环境为:VS2017
编译版本为:debug
编译结果为:X64和X86
测试结果:X86接收组播正常,X64接收报文不正常
代码如下:

  1. 初始化组播socket:
    int ret;
    udpsockfd[Task[TaskId]->TaskUdpNo].sockfd = ::socket(AF_INET,SOCK_DGRAM,0); //创建socket
    if(INVALID_SOCKET == udpsockfd[Task[TaskId]->TaskUdpNo].sockfd)
    {
    Sleep(500);
    continue;
    }

        //1.设置允许其它进程使用绑定的地址
        BOOL bReuse=TRUE;
        ret = ::setsockopt(udpsockfd[Task[TaskId]->TaskUdpNo].sockfd,SOL_SOCKET,SO_REUSEADDR,(char*)&bReuse,sizeof(BOOL));
        if(ret == SOCKET_ERROR)
        { 
            ::shutdown(udpsockfd[Task[TaskId]->TaskUdpNo].sockfd, 2);
            ::closesocket(udpsockfd[Task[TaskId]->TaskUdpNo].sockfd); 
            udpsockfd[Task[TaskId]->TaskUdpNo].sockfd = INVALID_SOCKET;
            Sleep(100);
            continue;
        } 
    
        //2.绑定端口
        SOCKADDR_IN addr;   
        addr.sin_family = AF_INET;   
        addr.sin_port = htons((WORD)udpsockfd[Task[TaskId]->TaskUdpNo].LocalUdpPort);   
        addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);   
    
        int len = sizeof(sockaddr);   
        ret = bind(udpsockfd[Task[TaskId]->TaskUdpNo].sockfd,(sockaddr*)&addr,len);   //绑定后,只接收绑定设置的报文
        if(ret==SOCKET_ERROR)
        {
            shutdown(udpsockfd[Task[TaskId]->TaskUdpNo].sockfd, 2);
            ::closesocket(udpsockfd[Task[TaskId]->TaskUdpNo].sockfd); 
            udpsockfd[Task[TaskId]->TaskUdpNo].sockfd = INVALID_SOCKET;
            Sleep(100);
            continue;
        }
    
        //3.加入多播组
        ip_mreq mcast;
        mcast.imr_interface.S_un.S_addr=INADDR_ANY;
        //mcast.imr_multiaddr.S_un.S_addr=inet_addr("236.8.8.8");
        inet_pton(AF_INET, "236.8.8.8", (void*)&mcast.imr_multiaddr.S_un);
        if(setsockopt(udpsockfd[Task[TaskId]->TaskUdpNo].sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char*)&mcast,sizeof(mcast)))
        {
            ::shutdown(udpsockfd[Task[TaskId]->TaskUdpNo].sockfd, 2);
            ::closesocket(udpsockfd[Task[TaskId]->TaskUdpNo].sockfd); 
            udpsockfd[Task[TaskId]->TaskUdpNo].sockfd = INVALID_SOCKET;
            Sleep(100);
            continue;
        }
    
        //4.设置组播数据不回环
        int loop=0;//1为数据回环
        ret = ::setsockopt(udpsockfd[Task[TaskId]->TaskUdpNo].sockfd,IPPROTO_IP,IP_MULTICAST_LOOP,(char*)&loop,sizeof(loop));
        if(ret == SOCKET_ERROR)
        { 
            ::shutdown(udpsockfd[Task[TaskId]->TaskUdpNo].sockfd, 2);
            ::closesocket(udpsockfd[Task[TaskId]->TaskUdpNo].sockfd); 
            udpsockfd[Task[TaskId]->TaskUdpNo].sockfd = INVALID_SOCKET;
            Sleep(100);
            continue;
        } 
    
        unsigned long ul1 = 1;  //非阻塞模式 
        ret = ::ioctlsocket(udpsockfd[Task[TaskId]->TaskUdpNo].sockfd, FIONBIO, (unsigned long*)&ul1); 
        if(ret == SOCKET_ERROR)
        { 
            ::shutdown(udpsockfd[Task[TaskId]->TaskUdpNo].sockfd, 2);
            ::closesocket(udpsockfd[Task[TaskId]->TaskUdpNo].sockfd); 
            udpsockfd[Task[TaskId]->TaskUdpNo].sockfd = INVALID_SOCKET;
            Sleep(100);
            continue;
        } 
    
        //可以发送广播
        if(::setsockopt(udpsockfd[Task[TaskId]->TaskUdpNo].sockfd, SOL_SOCKET, SO_BROADCAST,(char*)&ul1, sizeof (unsigned long))==SOCKET_ERROR)
        {
            ::shutdown(udpsockfd[Task[TaskId]->TaskUdpNo].sockfd, 2);
            ::closesocket(udpsockfd[Task[TaskId]->TaskUdpNo].sockfd); 
            udpsockfd[Task[TaskId]->TaskUdpNo].sockfd = INVALID_SOCKET;
            Sleep(100);
            continue;
        }
        udpsockfd[Task[TaskId]->TaskUdpNo].InitialTaskUdp = TRUE;
        udpsockfd[Task[TaskId]->TaskUdpNo].LocalIp = MyIpA;
    
  2. 接收组播报文:
    UINT taskUdpRecvPkt( LPVOID pParam )
    {
    fd_set rdset,wrset;
    int max_fd,inaddrlen;
    struct sockaddr_in inaddr;
    BYTE i,TaskId = (BYTE)(LONG_PTR)pParam;
    struct timeval to, to_wait;

    if(g_UdpRECV_Has_Create)return 1; //接收线程只创建1个
    g_UdpRECV_Has_Create = TRUE;

    bThreadBusy[LIMIT_TASK_NUM*3-1]=TRUE;
    while (true)
    {
    if(bThreadExit)break;

    FD_ZERO(&rdset);
    FD_ZERO(&wrset);
    max_fd = -1;
    for(i=0;i<MAX_UDP_NUM_TASK;i++)     //多个udp接收,逐个判断
    {
        if(i==UDP_NO_TASKFSA31C || i==UDP_NO_TASKFSA31C_B)continue;
        if(udpsockfd[i].InitialTaskUdp)
        {
            FD_SET(udpsockfd[i].sockfd, &rdset);
            FD_SET(udpsockfd[i].sockfd, &wrset);
            if(max_fd < (int)udpsockfd[i].sockfd)
                max_fd = (int)udpsockfd[i].sockfd;
        }
    }
    if(max_fd < 0 ){
        Sleep(1000);    //没有可用连接,等待1秒钟.
        continue;
    }
    
    to.tv_sec  = 0;
    to.tv_usec = 5000;  //5ms
    int status = select(max_fd+1, &rdset, &wrset,NULL, &to);
    if(status == 0) {
        // select timeout.
        continue;
    }
    else if((status < 0) && (errno ==EINTR)) {
        continue;
    }
    else if(status < 0) {
        perror("process_data_via_udp select error");
        return 1;
    }
    
    //有报文进来,开始接收
    for(i=0;i<MAX_UDP_NUM_TASK;i++)     //多个udp接收,逐个判断
    {
        if(i==UDP_NO_TASKFSA31C || i==UDP_NO_TASKFSA31C_B)continue;
        if(udpsockfd[i].InitialTaskUdp && (FD_ISSET(udpsockfd[i].sockfd, &rdset)))
        {
            int rx_len = recvfrom(udpsockfd[i].sockfd, (char*)&g_RecvUdpPkt[g_Net_UDPNrRec_Buf_Item_In_Pt].m_Buffer[0], MAX_NET_RECV_BUFFER_SIZE, 
                0, (struct sockaddr*)&inaddr, &inaddrlen);
    
            if((rx_len > 0)/* && (udpsockfd[i].MyIp != inaddr.sin_addr.s_addr)*/)
            {
                g_RecvUdpPkt[g_Net_UDPNrRec_Buf_Item_In_Pt].m_RecvIP  = htonl(inaddr.sin_addr.s_addr);
                g_RecvUdpPkt[g_Net_UDPNrRec_Buf_Item_In_Pt].m_RecvLen = rx_len;
                g_RecvUdpPkt[g_Net_UDPNrRec_Buf_Item_In_Pt].m_UDPPORT = udpsockfd[i].LocalUdpPort;
    
                g_Net_UDPNrRec_Buf_Item_In_Pt++;
                if(g_Net_UDPNrRec_Buf_Item_In_Pt >= MAX_NET_RECV_UDP_ITEM_NUM)
                {
                    g_Net_UDPNrRec_Buf_Item_In_Pt = 0;
                }
            }
        }
    }
    
    to_wait.tv_sec  = 0;
    to_wait.tv_usec = 2000;
    //sleep
    select(0, NULL, NULL, NULL, &to_wait); //sleep 2 ms.
    

    }

    for(i=0;i<MAX_UDP_NUM_TASK;i++)
    {
    if(i==UDP_NO_TASKFSA31C || i==UDP_NO_TASKFSA31C_B)continue;

    if(udpsockfd[i].sockfd != INVALID_SOCKET)
    {
        shutdown(udpsockfd[i].sockfd, 2);
        ::closesocket(udpsockfd[i].sockfd); 
        udpsockfd[i].sockfd = INVALID_SOCKET;
    }
    

    }
    bThreadBusy[LIMIT_TASK_NUM*3-1]=FALSE;
    return 0;
    }

  • 写回答

1条回答 默认 最新

  • dabocaiqq 2019-05-26 21:47
    关注
    评论

报告相同问题?

悬赏问题

  • ¥15 求解 yolo算法问题
  • ¥15 虚拟机打包apk出现错误
  • ¥30 最小化遗憾贪心算法上界
  • ¥15 用visual studi code完成html页面
  • ¥15 聚类分析或者python进行数据分析
  • ¥15 三菱伺服电机按启动按钮有使能但不动作
  • ¥15 js,页面2返回页面1时定位进入的设备
  • ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复
  • ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。
  • ¥20 ML307A在使用AT命令连接EMQX平台的MQTT时被拒绝