放眼市場上各種各樣的JSR82 MIDlets,有一點需要注意,一些MIDlets并沒有以一種合適的方式處理服務發現協議(SDP)記錄。在藍牙領域內SDP記錄是非常難以領會的,但是在JSR82中并沒有這么困難。
這篇短小的文章會就SDP記錄的一般問題給予一些建議。
我們先簡要地看看為什么需要SDP記錄。SDP記錄是一種用來確認設備上的一種特定服務的記錄。沒有SDP記錄,一部移動電話就不可能檢測到另一個設備上的服務。大部分的電話擁有一個以上的SDP記錄,例如,它們很可能有對于L2CAP和串口的記錄。
關于SDP記錄最主要的問題的就是很多開發者忘記了從數據庫中刪除SDP記錄。這就導致了最終用戶不能重新連接來運行游戲。
下面兩張簡單的圖片說明了這個問題:
圖1 SDP連接成功
如圖1所示兩個MIDlets正在試圖進行連接,并且連接成功。
圖2 SDP連接失敗
在圖2中我們可以看到,一個MIDlet再一次嘗試連接(可能是同一用戶或者一個新用戶)。連接失敗,因為這個MIDlet試圖連接的SDP記錄沒有監聽器,所以Bluetooth棧除了拒絕連接別無選擇。經常發生的情況是,客戶端MIDlet接收到兩者的SDP記錄,但是只選擇第一個進行連接,因為它只希望在一個服務器上有一個SDP記錄。
在下面的代碼示例中了,展示了一個簡單的服務器。這個例子關注了必須的close()調用。
例子:
public class SEMCSPPServer extends Thread
{
PRivate StreamConnectionNotifier server = null;
private StreamConnection sppConnection = null;
public SEMCSPPServer()
{
// This will create create an SDP record in the dB
try
{
server = (StreamConnectionNotifier)Connector.open( "BTspp://localhost:ea
}
catch( Exception e ) {}
}
public void run()
{
// Wait for connections
try
{
sppConnection = server.acceptAndOpen();
}
catch( Exception e ) { e.printStackTrace(); }
// Let the server do something fun here
try
{
// Open the Streams to be used for communications
InputStream in = sppConnection.openInputStream();
OutputStream out = sppConnection.openOutputStream();
// Let the server do something fun here
while()
{
}
// Server is done, now cleanup
// Close the Streams
try
{
in.close();
}
catch( IOException ioe ) {}
try
{
out.close();
}
catch( IOException ioe ) {}
in = null;
out = null;
}
catch( Exception e ) {}
// Close the Connection
try
{
sppConnection.close();
}
catch( IOException ioe ) {}
sppConnection = null;
// To make it possible for a client to re-connect
// we need to remove the current SDP record
// If the MIDlet ends here we SHOULD still
// close the notifier, but the MIDlet environment will
// clean-up after us
server.close();
} // run
}
自然地,你就擁有了幾種類型不同的服務器管理者,它們管理所有的服務器連接,并且使SDP記錄重新利用,例如,有一種服務器管理者始終監聽連接。例如,在一個多玩家的藍牙游戲中允許玩家隨時進入和退出。
服務器管理者例子:
// A simple server handler
public class SEMCSPPServerHandler
{
private StreamConnectionNotifier server = null;
private StreamConnection sppConnection = null;
public SEMCSPPServerHandler()
{
// This will create create an SDP record in the dB
try
{
server = (StreamConnectionNotifier)Connector.open( "btspp://localhost:ea
}
catch( Exception e ) {}
while( true )
{
// Wait for connections
try
{
sppConnection = server.acceptAndOpen();
}
catch( Exception e ) { e.printStackTrace(); }
if( sppConnection != null )
{
SEMCSPPServer sp = new SEMCSPPServer( sppConnection );
sp.start();
sp = null;
}
// The server handler is now ready to deal with new connections
// Note, there is no need to create a new SDP record
}
// Remove the SDP record
server.close();
}
}
// A simple server class to deal with 1 connection
public class SEMCSPPServer extends Thread
{
private StreamConnection sppConnection = null;
public SEMCSPPServer( StreamConnection sppConnection )
{
this.sppConnection = sppConnection;
}
public void run()
{
try
{
// Open the Streams to be used for communications
InputStream in = sppConnection.openInputStream();
OutputStream out = sppConnection.openOutputStream();
// Let the server do something fun here
while()
{
}
// Server is done, now cleanup
// Close the Streams
try
{
in.close();
}
catch( IOException ioe ) {}
try
{
out.close();
}
catch( IOException ioe ) {}
in = null;
out = null;
}
catch( Exception e ) {}
// Close the Connection
try
{
sppConnection.close();
}
catch( IOException ioe ) {}
sppConnection = null;
// The server is no longer active
} // run
}
需要學習的經驗
如果Connector. open()調用沒有很好的管理,除非退出MIDlet(這種情況下SDP數據庫被在一個清空)否則要重新連接到那個SDP記錄是不可能的?,F實生活中,你必須要退出游戲然后重新啟動,這將會使最終用戶灰心地離開。
當然,在你可以的應用中可能包括多于一個的SDP記錄,但是對于適當的功能性需求要確保MIDlet監聽所有的記錄。
原文地址:http://developer.sonyeriCSSon.com/site/global/techsupport/tipstrickscode/java/p_advice_bluetooth_sdp_game+server.jsp
(出處:http://www.49028c.com)
新聞熱點
疑難解答