顯示具有 java 標籤的文章。 顯示所有文章
顯示具有 java 標籤的文章。 顯示所有文章

2014年2月17日 星期一

[java] UnknownHostException in osx 10.9 with JDK7

週末硬碟掛點後,裝好 osx 10.9 與 JDK 7 上工的第一天,遇到了這樣的錯誤
Exception in thread "main" java.net.UnknownHostException: pj-pc.m.c.t: pj-pc.m.c.t: nodename nor servname provided, or not known
    at java.net.InetAddress.getLocalHost(InetAddress.java:1473)
    at net.muzee.paid.channels.Foo.main(Foo.java:8)
Caused by: java.net.UnknownHostException: pj-pc.m.c.t: nodename nor servname provided, or not known
    at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
    at java.net.InetAddress$1.lookupAllHostAddr(InetAddress.java:901)
    at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1293)
    at java.net.InetAddress.getLocalHost(InetAddress.java:1469)
    ... 1 more
把問題最小化後,可以用這樣的 code 來重現:
package net.muzee.paid.channels;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class HostTest {
    public static void main(String[] args) throws UnknownHostException {
        String localHostname = InetAddress.getLocalHost().getHostName();
        System.out.println(localHostname);

    }
}
看起來是在 osx 10.9 預設是沒有設 localhost 名稱,而 JDK 因為取不到名為 localhost 的記錄,就繼續正常的流程,取 domain 然後進行驗證。最後得出 UnknownHostException 的結論。
在一篇文章中找到,如何改變 osx 的 localhost 名稱。設定前是沒有值的情況:
qty:~ qrtt1$ scutil --get HostName
HostName: not set
設定完成後,就可以看到 localhost 字樣(如果你有其它需要,也能設成不同的值):
qty:~ qrtt1$ scutil --set HostName 'localhost'
qty:~ qrtt1$ scutil --get HostName
localhost

2009年7月7日 星期二

UPnP Actoin Invoke

最近開始學習撰寫手機程式,這使我不得不思考過去一些使用 Library 能完成的事項要試著在沒有 Library 的情況下完成。以 UPnP Action 呼叫為例,在 Java 有 CyberLink for Java Library 能夠使用。

今天就在想,一個完整的 UPnP Library 包含 UPnP Device、Service 的組裝,並且在執行期負責做 Device、Service 的廣告。另外,它還需要提供 Control Point 與 UPnP Service 打交道。真的要使用 UPnP Service 您必需有 Control Point,UPnP 服務會以 Http Server 的方式,等待來自 Control Point Actoin Invoke。若僅是寫手持裝置上的 App 實在不需要整套 UPnP Library,頂多有 Control Point 就足夠。

不過,大家 Library 都相當完整不可分割。只好重新思考自己由底層的 protocol 下手。再次翻閱 UPnP 規格書,要對控制 UPnP Action 其實並不困難:


事實上,有了資料格式,整件事就簡化成了填空題。以操作 UPnP AV Media Server 內 Connection Manager 服務提供的 GetProtocolInfo Action 為例,下圖為 在 UPnP Spy 提供的視窗介面,您可以見到 GetProtocolInfo 有二個回傳變數 (無輸入變數),一個為 Source,另一個為 Sink,所以您應該要期待即使是使用 Socket 與 UPnP Service 溝通,也要有這項項回傳值:


而控制協定要求我們要填寫 POST Path,您可以在 Service Description Language 文件找到,透過 UPnP Spy 能知道此 Service 的控制 URL 為「_urn:schemas-upnp-org:service:ConnectionManager_control」。另外,您還需準備一個 SOAPACTION Header,規則是「serviceType + '#' + actionName」。最後 Http Body,依規格書的建議填上適當的 SOAP 標籤與 ActionName、ActionArgument,需傳送內容如下:

POST /_urn:schemas-upnp-org:service:ConnectionManager_control HTTP/1.1
HOST: 192.168.6.18
Content-Type: text/xml; charset="utf-8"
Content-Length: 313
SOAPACTION: "urn:schemas-upnp-org:service:ConnectionManager:1#GetProtocolInfo"
Connection: close

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<u:GetProtocolInfo xmlns:u="urn:schemas-upnp-org:service:ConnectionManager:1"></u:GetProtocolInfo>
</s:Body>
</s:Envelope>

如果,Action Invoke 成功,它就會回傳下列訊息:

HTTP/1.1 200 OK
EXT:
CONTENT-TYPE: text/xml ; charset="utf-8"
SERVER: Windows NT/5.0, UPnP/1.0, Intel CLR SDK/1.0
Content-Length: 521

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:GetProtocolInfoResponse xmlns:u="urn:schemas-upnp-org:service:ConnectionManager:1">
<Source>http-get:*:audio/mpeg:*,http-get:*:image/jpeg:*,http-get:*:text/plain:*,http-get:*:application/octet-stream:*,http-get:*:audio/x-mpegurl:*</Source>
<Sink />
</u:GetProtocolInfoResponse>
</s:Body>
</s:Envelope>

透過簡單的實驗知道,即使不依賴 Library 要實現簡單的 UPnP Control 是可行的。