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

编译环境为: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;
    }

c++

1个回答

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!

相似问题

2
rabbitmq 怎么实现多个消费者同时接收一个队列的消息?
1
zookeeper客户端接收到zokeeper的更新事件后更新本地缓存需要自己实现吗?
2
C#如何把一个大的数组分割为固定大小的数组?
0
python实现Redis的订阅与发布(接收到的消息type为subscribe)
2
通过C++/java socket向服务器端传递字符串并接收服务器的反馈字符串与使用浏览器实现相同功能有何区别?
0
如何通过FSMC实现STM32与FPGA的同时相互读写数据?
1
野火 RTT 改的 三个串口 dma 接收 接收后处理数据,但是串口一直不能正常发送数据
2
PHP接收前端传来的图片并转化为base64格式
1
两个ESP8266同时发送数据给另一个ESP8266的时候,接收的时候会把两个数据掺杂在一起怎么办
0
jmeter 两个请求参数传递,接口接收的是数组,这个参数来源于第一个接口的返回值
1
局域网组播同时收发的问题
2
Java后台返回数组给微信小程序前台
4
webapi [FromBody] 接收数据不对
1
ffmpeg实现web上视频转码为mp4格式用video标签却无法播放
1
51单片机的接收上位机指令,并控制步进电机
4
前端接收后端传来的cookie 怎么操作!!!
1
c#、java 怎么解析必能信2000x超声波焊接设备发送出来的数据
2
使用nodejs如何做一个对外接口,接收对方传送的数据?
0
java的静态代理代理类不实现接口也能实现代理功能?
1
大佬们,java的静态代理的代理类不实现接口也能实现代理功能吧?初学者求解,谢谢啦