2013-04-01 2 views
7

from here으로 찍은 내 안드로이드 응용 프로그램에 매우 간단한 SSDP 기능을 구현하려고합니다.SSDP를 사용하여 적절한 UDP 패킷을 수신 할 수 없습니다.

내 응용 프로그램은 문제없이 관련 M-SEARCH 메시지가 포함 된 UDP 패킷을 브로드 캐스트 주소로 보냅니다. 문제는 UPNP 서버를 실행중인 다른 장치에서 적절한 응답을 다시 받아야한다는 것입니다. 웬일인지, 나는 안드로이드 장치로부터 보내어 졌던 정확한 같은 패킷만을 받고있다.

MainActivity.java UDP 패킷 전송이 실제로 난 문제에 아마 관련이없는 SSDP 방송 문자열 을 (건설에 대한

public class SSDPSocket { 
    SocketAddress mSSDPMulticastGroup; 
    MulticastSocket mSSDPSocket; 
    InetAddress broadcastAddress; 

    public SSDPSocket() throws IOException { 
     mSSDPSocket = new MulticastSocket(55325); //Bind some random port for receiving datagram 
     broadcastAddress = InetAddress.getByName(SSDPConstants.ADDRESS); 
     mSSDPSocket.joinGroup(broadcastAddress); 
    } 

    /* Used to send SSDP packet */ 
    public void send(String data) throws IOException { 
     DatagramPacket dp = new DatagramPacket(data.getBytes(), data.length(), 
       broadcastAddress,SSDPConstants.PORT); 

     mSSDPSocket.send(dp); 
    } 

    /* Used to receive SSDP packet */ 
    public DatagramPacket receive() throws IOException { 
     byte[] buf = new byte[1024]; 
     DatagramPacket dp = new DatagramPacket(buf, buf.length); 

     mSSDPSocket.receive(dp); 

     return dp; 
    } 

    public void close() { 
     if (mSSDPSocket != null) { 
      mSSDPSocket.close(); 
     } 
    } 
} 

SSDPSearchMsg.java을 수행

@Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     WifiManager wm = (WifiManager)getSystemService(Context.WIFI_SERVICE); 
     WifiManager.MulticastLock multicastLock = wm.createMulticastLock("multicastLock"); 
     multicastLock.setReferenceCounted(true); 
     multicastLock.acquire(); 

     setContentView(R.layout.activity_main); 

     ((Button)this.findViewById(R.id.btnSendSSDPSearch)).setOnClickListener(this); 
    } 

@Override 
    public void onClick(View v) { 
     switch (v.getId()) { 
     case R.id.btnSendSSDPSearch: 
      new Thread(new Runnable() { 

       @Override 
       public void run() { 
        SendMSearchMessage(); 
       } 
      }).start(); 

     default: 
      break; 
     } 
    } 

private void SendMSearchMessage() { 

       SSDPSearchMsg searchContentDirectory = new SSDPSearchMsg(SSDPConstants.ST_ContentDirectory); 
    SSDPSearchMsg searchAVTransport = new SSDPSearchMsg(SSDPConstants.ST_AVTransport); 
    SSDPSearchMsg searchProduct = new SSDPSearchMsg(SSDPConstants.ST_Product); 

    SSDPSocket sock; 
    try { 
     sock = new SSDPSocket(); 
     for (int i = 0; i < 2; i++) { 
      sock.send(searchContentDirectory.toString()); 
      sock.send(searchAVTransport.toString()); 
      sock.send(searchProduct.toString()); 
     } 

     while (true) { 
      DatagramPacket dp = sock.receive(); //Here, I only receive the same packets I initially sent above 
      String c = new String(dp.getData()); 
      System.out.println(c); 
     } 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     Log.e("M-SEARCH", e.getMessage()); 

    } 

SSDPSocket.java 경험이있을 때만)

public class SSDPSearchMsg { 
    static final String HOST = "Host:" + SSDP.ADDRESS + ":" + SSDP.PORT; 
    static final String MAN = "Man:ssdp:discover"; 
    static final String NEWLINE = System.getProperty("line.separator"); 

    int mMX = 3; /* seconds to delay response */ 
    String mST;  /* Search target */ 

    public SSDPSearchMsg(String ST) { 
     mST = ST; 
    } 

    public int getmMX() { 
     return mMX; 
    } 

    public void setmMX(int mMX) { 
     this.mMX = mMX; 
    } 

    public String getmST() { 
     return mST; 
    } 

    public void setmST(String mST) { 
     this.mST = mST; 
    } 

    @Override 
    public String toString() { 
     StringBuilder content = new StringBuilder(); 

     content.append(SSDP.SL_MSEARCH).append(NEWLINE); 
     content.append(HOST).append(NEWLINE); 
     content.append(MAN).append(NEWLINE); 
     content.append(mST).append(NEWLINE); 
     content.append("MX:" + mMX).append(NEWLINE); 
     content.append(NEWLINE); 

     return content.toString(); 
    } 
} 
<uses-permission android:name="android.permission.INTERNET"/> 
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" /> 
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> 
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 

내가하지 에뮬레이터에서, 실제 장치에서 응용 프로그램을 테스트하고 있습니다 : (210) SSDPConstants.java

public class SSDPConstants { 
    /* New line definition */ 
    public static final String NEWLINE = "\r\n"; 

    public static final String ADDRESS = "239.255.255.250"; 
    public static final int PORT = 1900; 

    /* Definitions of start line */ 
    public static final String SL_NOTIFY = "NOTIFY * HTTP/1.1"; 
    public static final String SL_MSEARCH = "M-SEARCH * HTTP/1.1"; 
    public static final String SL_OK = "HTTP/1.1 200 OK"; 

    /* Definitions of search targets */ 
    public static final String ST_RootDevice = "St: rootdevice"; 
    public static final String ST_ContentDirectory = "St: urn:schemas-upnp-org:service:ContentDirectory:1"; 
    public static final String ST_AVTransport = "St: urn:schemas-upnp-org:service:AVTransport:1"; 
    public static final String ST_Product = "St: urn:av-openhome-org:service:Product:1"; 

    /* Definitions of notification sub type */ 
    public static final String NTS_ALIVE = "NTS:ssdp:alive"; 
    public static final String NTS_BYE = "NTS:ssdp:byebye"; 
    public static final String NTS_UPDATE = "NTS:ssdp:update"; 
} 

는 또한 매니페스트 관련 권한이 포함되어 있는지 확인했다.

도움을 주시면 감사하겠습니다.

덧글 추가 편집 :

멀티 캐스트 자체는 문제없이 작동합니다. SSDP 기능을 테스트하기 위해 BubbleUPNP라는 앱을 다운로드했습니다. 아니나 다를까, 와이어 샤크가 제대로 SSDP 프로토콜에 방송 주소로 휴대 전화에서 보낸 모든 메시지를 캡처 :

M-SEARCH * HTTP/1.1 

Man: "ssdp:discover" 

Mx: 3 

Host: 239.255.255.250:1900 

St: urn:schemas-upnp-org:service:AVTransport:1 

그리고

HTTP/1.1 200 OK 

ST:urn:schemas-upnp-org:service:ContentDirectory:1 

USN:uuid:d5829e90-73ce-4213-9ad1-4e75dbdd0232::urn:schemas-upnp-org:service:ContentDirectory:1 

Location:http://10.175.95.4:2869/upnphost/udhisapi.dll?content=uuid:d5829e90-73ce-4213-9ad1-4e75dbdd0232 

OPT:"http://schemas.upnp.org/upnp/1/0/"; ns=01 

01-NLS:05f3dd08b4b4b5aafa1fe983fa447f49 

Cache-Control:max-age=900 

Server:Microsoft-Windows-NT/5.1 UPnP/1.0 UPnP-Device-Host/1.0 

그래서 그래, 이것은 의심의 여지없이 응답, 구현 문제. 장치에 문제가 없습니다.

+0

SSDP 패킷 만 보았을 때 가장 좋은 WireShark 필터는 ** (udp에 "HTTP/1.1"이 포함되어 있고 (udp에는 0a : 53 : 54 : 3a가 포함되어 있음) 또는 (udp 0a : 59 : 54 : 3a)) ** 해당 16 진수는 줄의 시작 부분에 "ST :"및 "NT :"입니다. –

답변

4

이상한. 문제는 해결되었지만 실제로 작동하게 된 이유는 확실하지 않습니다.여기

내가 만든 몇 가지 변경 사항은 다음과 같습니다

을 대신 고정 포트를 할당, 나는 동적으로 사용 가능한 포트를 할당했다.

public class SSDPSocket { 
    SocketAddress mSSDPMulticastGroup; 
    MulticastSocket mSSDPSocket; 
    InetAddress broadcastAddress; 

    public SSDPSocket() throws IOException { 

     mSSDPSocket = new MulticastSocket(); 
     broadcastAddress = InetAddress.getByName(SSDPConstants.ADDRESS); 
     mSSDPSocket.joinGroup(broadcastAddress); 
    } 
... 
} 

또한 M- 검색 메시지 구조와 그 순서를 변경했습니다.

public class SSDPSearchMsg { 
    static final String HOST = "Host: " + SSDPConstants.ADDRESS + ":" + SSDPConstants.PORT; 
    static final String MAN = "Man: \"ssdp:discover\""; 
    static final String NEWLINE = "\r\n"; 

    int mMX = 3; /* seconds to delay response */ 
    String mST;  /* Search target */ 

    public SSDPSearchMsg(String ST) { 
     mST = ST; 
    } 

    public int getmMX() { 
     return mMX; 
    } 

    public void setmMX(int mMX) { 
     this.mMX = mMX; 
    } 

    public String getmST() { 
     return mST; 
    } 

    public void setmST(String mST) { 
     this.mST = mST; 
    } 

    @Override 
    public String toString() { 
     StringBuilder content = new StringBuilder(); 

     content.append(SSDPConstants.SL_MSEARCH).append(NEWLINE); 
     content.append(MAN).append(NEWLINE); 
     content.append("Mx: " + mMX).append(NEWLINE); 
     content.append(HOST).append(NEWLINE); 
     content.append(mST).append(NEWLINE); 
     content.append(NEWLINE); 

     return content.toString(); 
    } 
} 

갑자기 모든 것이 작동합니다. 그것이 효과가있는 이유는 저 밖에 있습니다. 나의 이전 구현은 내가 말할 수있는 한 SSDP 프로토콜을 따른다.

0

가능한 답변은 "오래된"장치가있을 수 있다는 것입니다. (자바에서) 분명히 멀티 캐스트 안드로이드 전에 고장 2.3.7

참조 : https://stackoverflow.com/a/9836464/139985

또 다른 가능성은 그것이 장치 별 문제가 있다는 것입니다; 예 : 이렇게 : https://stackoverflow.com/a/3714848/139985.

또 다른 멀티 캐스트 커널 CONFIGS에서 비활성화되어있다 (내가 말하는 게 아니에요 그것은 특정 문제가 ...이다) : http://code.google.com/p/android/issues/detail?id=51195 멀티 캐스트가 작동하지 않는 다른 원인의 범위가있는 것 같다

다양한 Android 기기 ...

+0

갤럭시 S3, 아이스크림 샌드위치에서 실행 중입니다 – l46kok

+0

마켓 플레이스에서 앱을 가져올 수 있었기 때문에 멀티 캐스팅이이 장치에서 제대로 작동합니다. 적절한 응답이 포함 된 M- 검색 메시지를 게시합니다. 나는 캡처 된 패킷으로 OP를 편집 할 것이다. – l46kok

+0

나는 그 때 아이디어에서이다. –

0

코드를 따라 일부 단어를 대문자로 변경했습니다. 그것은 작동합니다.

MSEARCH 메시지의 순서를 변경할 필요가 없습니다.

관련 문제