管理蓝牙SDP记录和游戏服务器之间连接

这是个转贴,不过涉及的内容我还没有学到,先贴在这里,等reading完82再回来看。
放眼市场上各种各样的JSR82 MIDlets,有一点需要注意,一些MIDlets并没有以一种合适的方式处理服务发现协议(SDP)记录。在蓝牙领域内SDP记录是非常难以领会的,但是在JSR82中并没有这么困难。
这篇短小的文章会就SDP记录的一般问题给予一些建议。
我们先简要地看看为什么需要SDP记录。SDP记录是一种用来确认设备上的一种特定服务的记录。没有SDP记录,一部移动电话就不可能检测到另一个设备上的服务。大部分的电话拥有一个以上的SDP记录,例如,它们很可能有对于L2CAP和串口的记录。
关于SDP记录最主要的问题的就是很多开发者忘记了从数据库中删除SDP记录。这就导致了最终用户不能重新连接来运行游戏。
下面两张简单的图片说明了这个问题:
图1
图1  SDP连接成功
如图1所示两个MIDlets正在试图进行连接,并且连接成功。
图1
 
图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:ea834a8566aa4e0fb02ce4c1a53700c9;name=SomeServer" );
    }
    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:ea834a8566aa4e0fb02ce4c1a53700c9;name=SomeServer" );
    }
    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记录是不可能的。现实生活中,你必须要退出游戏然后重新启动,这将会使最终用户灰心地离开。
当然,在你可以的应用中可能包括多于一个的SDP记录,但是对于适当的功能性需求要确保MIDlet监听所有的记录。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值