写了一个多播的,碰到一个问题,就是程序在编译到setsockopt时,老是暴错,错误代码是10049,我查了一下,意思好像是说多播地址有问题,我把地址改成224.5.6.7也不行(我在有的书里看到多播地址是224。*。*。*,MSDN里是234.*.*.*),试过无数次老是在这里碰到问题,我不明白,还请各位朋友帮忙看一下,在这里先谢过了有神说问题是“应该根据你使用的计算机的实际IP地址来设置。”不懂

解决方案 »

  1.   

    多播地址IPv4地址是 224.0.0.0 到 239.255.255.255之间,除了头三个路由器专用的保留地址之外都可以用10049 错误是 WSAEADDRNOTAVAIL错误       不能分配请求的地址。API调用中置顶的地址对那个函数来说无效时就会产生这样的错误。例如,
         在bind调用中指定一个IP地址,但却没有对应的本地IP接口,便会产生这样的错误。
      

  2.   

    struct ip_mreq stMreq;        stMreq.imr_multiaddr.s_addr = inet_addr(m_strUDPDesIPAddr);
    stMreq.imr_interface.s_addr = INADDR_ANY;//加入这句没有?
      

  3.   

    多点组播(Multicast)是基于UDP协议的通信方式。即点对多点的通信方式,分为:
    (1)有根方式:由一个点创建多播组,其他点加入该多播组后能与根节点进行单向通信。即后加入的节点互相不能通信
    (2)无根方式:多个点处于平等方式,两两都能双向通信。
     多播用于视频会议,聊天室等。下面是用Windows API做的创建多播SOCKET的代码:
     //----------------------------------------------------------------------
    //初始化并创建一个多播socket
    //参数:
    //McFlag: 仅接收、仅发送还是双向通信的标志
              JL_RECEIVER_ONLY - 仅接收
              JL_SENDER_ONLY - 仅发送
              JL_BOTH- 双向通信
    //返回:  TRUE :成功, FALSE:失败
    //_____________________________________________________________________________
    BOOL McSocket::Create (int McFlag)
    {
        //make sure the protocol and capacity exit
        WORD wVersionRequested;         //request version of winsock
    WSADATA wsaData;   //returned sock data     
    int rightsock=0;
    int ret;     WSAPROTOCOL_INFO* Proto_Info=NULL;
    DWORD length=0;
    BOOL Multicast_Supported=FALSE;
    INT iProto[2]; wVersionRequested = MAKEWORD( 2,2); 
        ret = WSAStartup( wVersionRequested, &wsaData );  //initial winsock
    if ( ret != 0 ) 
    {
    m_Errmsg="Winsock 启动失败";
    return FALSE;
    }                              
    else if ( LOBYTE( wsaData.wVersion ) != 2 ||HIBYTE( wsaData.wVersion ) != 2 ) //check version
    {
         m_Errmsg="Winsock 版本不对,请使用WINSOCK2.2";
    WSACleanup( );
    return FALSE;
        } 
        else //check protocol and capacity                             
    {
        
    iProto[0]=IPPROTO_UDP;
         iProto[1]=NULL;     ret=WSAEnumProtocols(iProto, (LPWSAPROTOCOL_INFO)Proto_Info,&length);
            if(ret==SOCKET_ERROR && WSAGetLastError() ==WSAENOBUFS)
    {
    Proto_Info=new WSAPROTOCOL_INFO[length/sizeof(WSAPROTOCOL_INFO)];
    if(Proto_Info==NULL)
    {
    m_Errmsg="申请内存时出错";
    WSACleanup();
    return FALSE;
    }
    ret=WSAEnumProtocols(iProto, (LPWSAPROTOCOL_INFO)Proto_Info,&length);
        if(ret==SOCKET_ERROR)
    {
    ret=WSAGetLastError();
    m_Errmsg.Format("无法读取协议信息,错误代码:%d",ret);
        delete[] Proto_Info;
    WSACleanup();
    return FALSE;
    }
    }
    //mod 1/9 else
    //mod 1/9 {
    for(int j=0;j<ret;j++)
    {
    if(Proto_Info[j].dwServiceFlags1 & XP1_SUPPORT_MULTIPOINT !=0 
    && Proto_Info[j].iAddressFamily==AF_INET )
    {
    Multicast_Supported=TRUE;
    rightsock=j;
    break;    ///mod 1/9 IMPORTANT!!!!
    }
    }
    if(!Multicast_Supported)
    {
    m_Errmsg="系统不支持组播或无相应协议";
    WSACleanup();
    return FALSE;
    }
    //mod 1/9 }

    }    //create a multipoint socket
    m_Socket=WSASocket(FROM_PROTOCOL_INFO ,
                       FROM_PROTOCOL_INFO ,
             FROM_PROTOCOL_INFO ,
       (LPWSAPROTOCOL_INFO)&(Proto_Info[rightsock]),
       0,
       WSA_FLAG_MULTIPOINT_C_LEAF|WSA_FLAG_MULTIPOINT_D_LEAF); if(m_Socket==INVALID_SOCKET)
        {
    ret=WSAGetLastError();
    m_Errmsg.Format("创建SOCKET时发生异常,错误代码:%d",ret);
    delete[] Proto_Info;
    WSACleanup( );
    return FALSE;
    }
    delete[] Proto_Info; //create the hidden window to recieave async notificateions
        RECT rect;    rect.left=0;
        rect.top=0;
        rect.right=0;
        rect.bottom=0;
        CWnd* pWnd=AfxGetMainWnd(); m_pMsgWnd=new CMsgWnd();
        if(m_pMsgWnd==NULL)
    {
            m_Errmsg="生成隐藏窗口时出错";
    closesocket(m_Socket);
    WSACleanup();
    return FALSE;
    }    
        if(!m_pMsgWnd->Create(NULL,"Message Window",0,rect,pWnd,0))
    {   
    m_Errmsg="生成隐藏窗口时出错";
    closesocket(m_Socket);
    WSACleanup();
    return FALSE;
    }    
        m_pMsgWnd->RegSock(this); //set the socket notification message
    if(WSAAsyncSelect(m_Socket,m_pMsgWnd->m_hWnd ,IP_EVENT,FD_CONNECT | FD_CLOSE | FD_WRITE | FD_READ)==SOCKET_ERROR )
    {
    ret=WSAGetLastError();
    m_Errmsg.Format( "在设定操作通知时出错,错误代码:%d",ret);

    closesocket(m_Socket);
    WSACleanup( );
    return FALSE;
    }
        
    //set the send and rcv buffer
    int rcvbuf;
    int rcvbufsize=sizeof(int);
    BOOL IsReuse;
    int reusesize=sizeof(BOOL); if(getsockopt(m_Socket,SOL_SOCKET,SO_RCVBUF,(char*)&rcvbuf,&rcvbufsize)!=SOCKET_ERROR)
    {
    if(rcvbuf<65536)
       rcvbuf=65536;
    setsockopt(m_Socket,SOL_SOCKET,SO_RCVBUF,(char*)&rcvbuf,rcvbufsize);
    // getsockopt(m_Socket,SOL_SOCKET,SO_RCVBUF,(char*)&rcvbuf,&rcvbufsize);
    }

    if(getsockopt(m_Socket,SOL_SOCKET,SO_SNDBUF,(char*)&rcvbuf,&rcvbufsize)!=SOCKET_ERROR)
    {
    if(rcvbuf<65536)
       rcvbuf=65536;
    setsockopt(m_Socket,SOL_SOCKET,SO_SNDBUF,(char*)&rcvbuf,rcvbufsize);
    // getsockopt(m_Socket,SOL_SOCKET,SO_SNDBUF,(char*)&rcvbuf,&rcvbufsize);
    } if(getsockopt(m_Socket,SOL_SOCKET,SO_REUSEADDR,(char*)&IsReuse,&reusesize)!=SOCKET_ERROR)
    {
    if(IsReuse==FALSE)
    IsReuse=TRUE;
    setsockopt(m_Socket,SOL_SOCKET,SO_REUSEADDR,(char*)&IsReuse,reusesize);
    } //join the socket to a multicast group
    if(WSAJoinLeaf(m_Socket, (struct sockaddr FAR * )&m_MultiGroup, sizeof(sockaddr), NULL, NULL, NULL, NULL, McFlag) == INVALID_SOCKET)
    {
    ret=WSAGetLastError();
    m_Errmsg.Format(" 加入多点组时出错,错误代码:%d",ret);

    closesocket(m_Socket);
    WSACleanup( );
    return FALSE;
    }
        return TRUE;
    }
    多播IP地址是个D类地址,但有些用于特殊用途,你可以查阅相关资料。你可以定义:
    #define DEFAULT_MULTIADDR   "234.5.6.7"
    对照一下看你哪里出的错
      

  4.   

    http://www.yesky.com/SoftChannel/72342371928702976/20040315/1777184.shtml
    用Visual C++编程实现局域网多播
    //Project Setting -> C/C++ -> Code Generation -> 确认选中"Debug Multithreaded"#include <iostream>
    #include <winsock2.h> //注意这里的include文件顺序
    #include <Ws2tcpip.h>
    #include <process.h> //_beginthread要求#pragma comment(lib, "ws2_32.lib")using namespace std;const char* MULTICAST_IP = "224.0.0.99"; //多播组地址
    const int MULTICAST_PORT = 2002; //多播组端口const int BUFFER_SIZE = 1024;void do_send(void* arg); //读取用户输入并发送到多播组线程函数
    void do_read(void* arg); //读物多播组数据函数int main()
    {
    WSAData wsaData;if( WSAStartup(MAKEWORD(2,2), &wsaData) != 0 )
    {
    cout<<"Error in WSAStartup"<<endl;
    return 0;
    }SOCKET server;
    server = socket(AF_INET, SOCK_DGRAM, 0); //创建一个UDP套接口
    cout<<"create socket: "<<server<<endl;int ret ;const int on = 1; //允许程序的多个实例运行在同一台机器上
    ret = setsockopt(server, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
    if( ret == SOCKET_ERROR )
    {
    WSACleanup();cout<<"Error in setsockopt(SO_REUSEADDR): "<<WSAGetLastError()<<endl;
    return 0;
    }const int routenum = 10;
    ret = setsockopt(server,IPPROTO_IP,IP_MULTICAST_TTL,(char*)&routenum,sizeof(routenum));
    if( ret == SOCKET_ERROR )
    {
    WSACleanup();cout<<"Error in setsockopt(IP_MULTICAST_TTL): "<<WSAGetLastError()<<endl;
    return 0;
    }const int loopback = 0; //禁止回馈
    ret = setsockopt(server,IPPROTO_IP,IP_MULTICAST_LOOP,(char*)&loopback,sizeof(loopback));
    if( ret == SOCKET_ERROR )
    {
    WSACleanup();cout<<"Error in setsockopt(IP_MULTICAST_LOOP): "<<WSAGetLastError()<<endl;
    return 0;
    }sockaddr_in local;
    memset(&local, 0, sizeof(local));
    local.sin_family = AF_INET;
    local.sin_port = htons(MULTICAST_PORT);
    local.sin_addr.S_un.S_addr = INADDR_ANY;ret = bind(server, (sockaddr*)(&local), sizeof(local));
    if( ret == SOCKET_ERROR )
    {
    WSACleanup();cout<<"Error in bind: "<<WSAGetLastError()<<endl;
    return 0;
    }ip_mreq mreq;
    memset(&mreq, 0, sizeof(mreq));
    mreq.imr_interface.S_un.S_addr = INADDR_ANY;
    mreq.imr_multiaddr.S_un.S_addr = inet_addr(MULTICAST_IP);
      

  5.   

    //加入一个多播组
    ret = setsockopt(server,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char*)&mreq,sizeof(mreq));
    if( ret == SOCKET_ERROR )
    {
    WSACleanup();cout<<"Error in setsockopt(IP_ADD_MEMBERSHIP): "<<WSAGetLastError()<<endl;
    return 0;
    }//创建了两个线程,一个读用户输入并发送,一个读多播组数据
    HANDLE hHandle[2];
    hHandle[0] = (HANDLE)_beginthread(do_send,0,(void*)server);
    hHandle[1] = (HANDLE)_beginthread(do_read,0,(void*)server);//如果用户输入结束,程序就终止了
    WaitForSingleObject(hHandle[0], INFINITE);WSACleanup();return 0;
    }void do_send(void* arg)
    {
    SOCKET server = (SOCKET)arg;char sendline[BUFFER_SIZE+1];sockaddr_in remote;
    memset(&remote, 0, sizeof(remote));
    remote.sin_addr.s_addr = inet_addr ( MULTICAST_IP );
    remote.sin_family = AF_INET ;
    remote.sin_port = htons(MULTICAST_PORT);for(;;) //读取用户输入知道用户输入"end"
    {
    cin.getline(sendline, BUFFER_SIZE);if(strncmp(sendline,"end",3)==0)
    break;//发送用户输入的数据到多播组
    sendto(server, sendline, strlen(sendline), 0, (sockaddr*)(&remote), sizeof(remote)); 
    }cout<<"do_send end..."<<endl;
    }void do_read(void* arg)
    {
    SOCKET server = (SOCKET)arg;char buf[BUFFER_SIZE+1];
    int ret;sockaddr_in client;
    int clientLen;for(;;) //一直读取知道主线程终止
    {
    clientLen = sizeof(client);
    memset(&client, 0, clientLen);ret = recvfrom(server, buf, BUFFER_SIZE, 0, (sockaddr*)(&clientLen), &clientLen);
    if ( ret == 0) //do_read在用户直接回车发送了一个空字符串
    {
    continue;
    }
    else if( ret == SOCKET_ERROR )
    {
    if( WSAGetLastError() == WSAEINTR ) //主线程终止recvfrom返回的错
    break;cout<<"Error in recvfrom: "<<WSAGetLastError()<<endl;
    break ;
    }
    buf[ret] = '\0';
    cout<<"received: "<<buf<<endl;
    }cout<<"do_read end..."<<endl;
    }
      

  6.   

    if (bind(socket1,(struct sockaddr*)&server,sizeof(server)) == SOCKET_ERROR)
    {
    switch(GetLastError())
    {
    case WSANOTINITIALISED: printf("A successful WSAStartup call must occur before using this function. "); break;
    case WSAENETDOWN      : printf("The network subsystem has failed. "); break;
    case WSAEACCES        : printf("An attempt was made to access a socket in a way forbidden by its access permissions. An example is using a broadcast address for sendto without broadcast permission being set using setsockopt. "); break;
    case WSAEADDRINUSE    : printf("A process on the machine is already bound to the same fully qualified address and the socket has not been ed to allow address reuse with SO_REUSEADDR. For example, the IP address and port are bound in the af_inet case. (See the SO_REUSEADDR socket option under setsockopt.) "); break;
    case WSAEADDRNOTAVAIL : printf("The specified address is not a valid address for this machine. "); break;
    case WSAEFAULT        : printf("The name or namelen parameter is not a valid part of the user address space, the namelen parameter is too small, the name parameter contains an incorrect address format for the associated address family, or the first two bytes of the memory block specified by name do not match the address family associated with the socket descriptor s. "); break;
    case WSAEINPROGRESS   : printf("A blocking Winsock call is in progress, or the service provider is still processing a callback function."); break;
    case WSAEINVAL        : printf("The socket is already bound to an address."); break;
    case WSAENOBUFS       : printf("Not enough buffers available; too many connections."); break;
    default: fprintf(stderr,"bind() failed with error %d\n",GetLastError()); break;
    }
    Sleep(10000);
    return false;
    }
    如果用的是自己的ip就不會錯
    1.server.sin_addr.s_addr=inet_addr("127.0.0.1"); ///server的地址 
    2.server.sin_addr.s_addr=inet_addr("local ip"); ///server的地址 
    不知為什麼?