如何在发送M-SEARCH后继续侦听SSDP响应



我想搜索网络上的Sat>IP服务器。Sat>IP服务器向其他Sat>IP服务和客户端宣传其存在。我不能继续发送M-SEARCH消息,而是它侦听服务器NOTIFY消息。

在初始化我的设备的网络设置后,我会发送m-SEARCH消息,如果已经有任何活动的Sat>IP服务器,我会得到响应。然而,我无法得到任何响应,如果我在发送M-SEARCH消息后打开Sat>IP服务器。

这是我的密码。

void SatIP::InitDiscoverThread()
{
    if(INVALID_THREAD_CHK == DiscoverThreadChk)
    {
        pthread_attr_t attr;
        pthread_attr_init(&attr);
        pthread_attr_setstacksize(&attr, PTHREAD_STACK_SIZE);
        printf("InitDiscoverThread pthread_createn");
        DiscoverThreadChk = PTH_RET_CHK(pthread_create(&DiscoverThreadID, &attr, DiscoverThreadFunc, this));
        if(DiscoverThreadChk != 0)
        {
            ASSERT(0);
        }
    }
}
void SatIP::FinalizeDiscoverThread()
{
    if(INVALID_THREAD_CHK != DiscoverThreadChk)
    {
        printf("FinalizeDiscoverThread pthread_canceln");
        pthread_cancel(DiscoverThreadID);
        DiscoverThreadChk = INVALID_THREAD_CHK;
        close(discoverSocket);
    }
}
void *SatIP::DiscoverThreadFunc(void* arg)
{
    SatIP* satip = (SatIP *)arg;
    satip->ListenSSDPResponse();
    pthread_exit(NULL);
}
bool SatIP::SendMSearchMessage()
{
    vSatIPServers.clear();
    FinalizeDiscoverThread();
    const char *searchSatIPDevice = "M-SEARCH * HTTP/1.1rn"    
                                           "HOST: 239.255.255.250:1900rn"     
                                           "MAN: "ssdp:discover"rn"     
                                           "MX: 2rn"          
                                           "ST: urn:ses-com:device:SatIPServer:1rnrn";
    struct sockaddr_in upnpControl, broadcast_addr;
    discoverSocket = socket(AF_INET, SOCK_DGRAM, 0);
    if (discoverSocket == INVALID_SOCKET)
    {
        printf("socked failed INVALID_SOCKETn");
        return false;
    }
    struct timeval tv;
    tv.tv_sec = 1;
    tv.tv_usec = 0;
    if(setsockopt(discoverSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv)) == SOCKET_ERROR)
    {
        printf("setsockopt timeout failedn");
        close(discoverSocket);
        return false;
    }
    socklen_t ttl = 2;
    if(setsockopt(discoverSocket, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) == SOCKET_ERROR)
    {
        printf("setsockopt TTL failedn");
        close(discoverSocket);
        return false;
    }
    if(setsockopt(discoverSocket, SOL_SOCKET, SO_BROADCAST, searchSatIPDevice, sizeof(searchSatIPDevice)) == SOCKET_ERROR)
    {
        printf("setsockopt broadcast failedn");
        close(discoverSocket);
        return false;
    }
    upnpControl.sin_family = AF_INET;
    upnpControl.sin_port = htons(0);
    upnpControl.sin_addr.s_addr = INADDR_ANY;
    if (bind(discoverSocket, (sockaddr*)&upnpControl, sizeof(upnpControl)) == SOCKET_ERROR)
    {
        printf("bind failedn");
        close(discoverSocket);
        return false;
    }
    broadcast_addr.sin_family = AF_INET;
    broadcast_addr.sin_port = htons(1900);
    broadcast_addr.sin_addr.s_addr = inet_addr("239.255.255.250");
    for(int i = 0; i < 3; i++)
    {
        if(sendto(discoverSocket, searchSatIPDevice, strlen(searchSatIPDevice), 0, (sockaddr *)&broadcast_addr, sizeof(broadcast_addr)) == SOCKET_ERROR)
        {
            //printf("sendto failedn");
            close(discoverSocket);
            return false;
        }
        else
        {
            usleep(10*100);
        }
    }
    InitDiscoverThread();
    return true;
}
void SatIP::ListenSSDPResponse()
{
    while(1)
    {
        char buf[512];
        memset(buf, 0, 512);
        struct sockaddr_in broadcast_addr;
        broadcast_addr.sin_family = AF_INET;
        broadcast_addr.sin_port = htons(1900);
        broadcast_addr.sin_addr.s_addr = inet_addr("239.255.255.250");
        int bcLen = sizeof(broadcast_addr);
        //bool bRet = false;
        while (recvfrom(discoverSocket, buf, 512, 0,  (struct sockaddr*)&broadcast_addr, (socklen_t*)&bcLen) > 0)
        {
            printf("buf:%sn",buf);
            SATIP_SERVER_DESCRIPTION stServerDesc;
            ostringstream ss;
            if(strstr(buf, "device:SatIPServer"))
            {
                int i = 0;
                char *deviceIp = strstr(buf, "LOCATION:") + 9; // get xml location including server description
                while(deviceIp[i] == ' ') i++; // remove spaces from string
                while(!isspace(deviceIp[i]))
                {
                    ss << deviceIp[i];
                    ++i;
                }
                stServerDesc.location = ss.str().c_str();
                printf("location:%sn",stServerDesc.location.c_str());
                ss.str(""); // clear ss
                i=0; // clear counter
                deviceIp = strstr(buf, "http://") + 7; // get ip address
                while(deviceIp[i] != ':')
                {
                    ss << deviceIp[i];
                    ++i;
                }
                stServerDesc.ipAddr = ss.str().c_str();
                printf("ipAddr:%sn", stServerDesc.ipAddr.c_str());
                DownloadDeviceDescription(&stServerDesc);
                stServerDesc.macAddr = GetMACAddressviaIP(stServerDesc.ipAddr);
                printf("macAddr:%sn", stServerDesc.macAddr.c_str());
                if(IsServerProperToAdd(&stServerDesc))
                    vSatIPServers.push_back(stServerDesc);
                printf("n");
                //bRet = true;
            }
            memset(buf, 0, 512);
        }
    }
}

如何解决此问题?如有任何帮助,我们将不胜感激。

监听SSDP通知消息与发送M-SEARCH消息无关。Sat>IP等设备定期向239.255.255.250发送NOTIFY消息,即使您不发送M-SEARCH消息。因此,您应该加入一个多播组并从该组接收。

通过将HELLO_PORT更改为1900,将HELLO_GROUP更改为"239.255.255.250",可以使用以下链接中的侦听程序。

http://ntrg.cs.tcd.ie/undergrad/4ba2/multicast/antony/example.html

/*
* listener.c -- joins a multicast group and echoes all data it receives from
*       the group to its stdout...
*
* Antony Courtney,  25/11/94
* Modified by: Frédéric Bastien (25/03/04)
* to compile without warning and work correctly
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

#define HELLO_PORT 1900
#define HELLO_GROUP "239.255.255.250"
#define MSGBUFSIZE 256
main(int argc, char *argv[])
{
     struct sockaddr_in addr;
     int fd, nbytes,addrlen;
     struct ip_mreq mreq;
     char msgbuf[MSGBUFSIZE];
     u_int yes=1;            /*** MODIFICATION TO ORIGINAL */
     /* create what looks like an ordinary UDP socket */
     if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) {
      perror("socket");
      exit(1);
     }
/**** MODIFICATION TO ORIGINAL */
    /* allow multiple sockets to use the same PORT number */
    if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0) {
       perror("Reusing ADDR failed");
       exit(1);
       }
/*** END OF MODIFICATION TO ORIGINAL */
     /* set up destination address */
     memset(&addr,0,sizeof(addr));
     addr.sin_family=AF_INET;
     addr.sin_addr.s_addr=htonl(INADDR_ANY); /* N.B.: differs from sender */
     addr.sin_port=htons(HELLO_PORT);
     /* bind to receive address */
     if (bind(fd,(struct sockaddr *) &addr,sizeof(addr)) < 0) {
      perror("bind");
      exit(1);
     }
     /* use setsockopt() to request that the kernel join a multicast group */
     mreq.imr_multiaddr.s_addr=inet_addr(HELLO_GROUP);
     mreq.imr_interface.s_addr=htonl(INADDR_ANY);
     if (setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0) {
      perror("setsockopt");
      exit(1);
     }
     /* now just enter a read-print loop */
     while (1) {
      addrlen=sizeof(addr);
      if ((nbytes=recvfrom(fd,msgbuf,MSGBUFSIZE,0,
               (struct sockaddr *) &addr,&addrlen)) < 0) {
           perror("recvfrom");
           exit(1);
      }
      puts(msgbuf);
     }
}

相关内容

  • 没有找到相关文章

最新更新