菜鸟向高手学习 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 matlab实现基于主成分变换的图像融合。
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料
  • ¥15 使用R语言marginaleffects包进行边际效应图绘制
  • ¥20 usb设备兼容性问题
  • ¥15 错误(10048): “调用exui内部功能”库命令的参数“参数4”不能接受空数据。怎么解决啊