保持Java蓝牙连接保持活动状态

8
我正在使用Bluecove API为我的电脑构建一个简单的Java蓝牙服务器。我也正在构建一个Android客户端应用程序,但问题似乎源自服务器端应用程序。
我确定有人已经在某个地方发布了答案,我已经尝试了不同的解决方案数天,并查看了每个可能的论坛,但我似乎无法保持套接字线程上的连接处于活动状态。
在从Android到计算机建立连接后,我可以进行消息交换,反之亦然,但是在交换字节后,Bluecove堆栈关闭并关闭套接字连接,即使我没有显式地告诉它connection.close()。
我尝试使用while(某个语句为true)循环来保持连接处于活动状态,它不再在接收到第一条消息后关闭套接字,但当我尝试从智能手机发送任何后续消息时,它无法接收任何新消息。虽然它基本上是活的,但却不知道为什么不能接收任何新消息。
对不起,这是我第一次发布,我不知道为什么代码的第一部分无法正确显示在页面上。
代码建立连接:
public BluetoothServer() {
    try {
        service = (StreamConnectionNotifier) 
            Connector.open("btspp://localhost:" + new UUID(0x1101).toString() + 
                                ";name=SampleServer");
        
        System.out.println("open connection");

        while (runState == true) {
        
            connection = (StreamConnection) service.acceptAndOpen();
                
            //send a greeting across to android
            outputStream = connection.openOutputStream();
            String greeting = "JSR-82 RFCOMM server says hello";
            outputStream.write(greeting.getBytes());
            
            //run thread that listens for incoming bytes through socket connection
            Thread t = new Thread(new ConnectedThread(connection));
            t.start();                
        }
            
    } catch(IOException e) {}
}

监听传入数据的线程代码

public void run() {
    try {    
        //open input stream to listen to data
        inputStream = connection.openInputStream();              
                                      
        byte buffer[] = new byte[1024];
        int bytes_read = inputStream.read(buffer);

        String received = new String(buffer, 0, bytes_read);
        System.out.println("received: " + received);
            
    } catch(IOException e) {}
}

客户端无法发送多个消息到服务器,但是服务器可以向客户端发送多个消息吗?哪个循环调用了您的run()方法?您能提供调用run()方法的代码吗? - Tim Hallyburton
过去我曾遇到非常类似的问题。但在我的情况下,连接并没有关闭,只是IO速度变慢了(在Android端)。经过调试,我们发现,在一段时间的不活动后,它会在Android端发生特定的超时(Android切换电源安全模式),而这个超时时间无法更改。为了保持连接的活跃,我们只需定期发送空包(一个字节)。希望这能有所帮助。 - Eugene
不要仅仅使用空的try/catch块。当抛出异常时记录下来,这将帮助您找到真正的原因。否则,您只是猜测。 - Don Srinath
1个回答

1

很遗憾我不能在我的机器上实际尝试你的代码,但我认为我看到了你的错误:在你的run()方法中,你从输入流中读取,将其打印到控制台,然后就结束了。在你的最后一行之后。

        System.out.println("received: " + received);

你的run()方法已经结束,线程已被运行时丢弃。你需要将接收放在while(true)或while(running)循环中。
我修改了你的代码,这是修改后的代码,但请记住我之前说过的话:我无法测试运行它,因此它完全未经测试!
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.bluetooth.UUID;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.io.StreamConnectionNotifier;


public class BluetoothServer {

    private boolean runState = true;

    public BluetoothServer(){

        try {
            StreamConnectionNotifier service = (StreamConnectionNotifier) Connector.open("btspp://localhost:" + new UUID(0x1101).toString() + ";name=SampleServer");
            System.out.println("open connection");

            while(runState == true){
                StreamConnection connection = (StreamConnection) service.acceptAndOpen();
                new Listener(connection).start();
            }

        } catch(IOException e) {
            e.printStackTrace();
        }
    }

    private class Listener extends Thread{

        private OutputStream os;
        private InputStream is;

        public Listener(StreamConnection connection){
            try {
                this.os = connection.openOutputStream();
                os.flush();
                this.is = connection.openInputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        public void run(){
            StringBuilder builder;
            try{
                String greeting = "JSR-82 RFCOMM server says hello";
                os.write(greeting.getBytes());

                while(true){
                    builder = new StringBuilder();
                    int tmp = 0;
                    while((tmp = is.read()) != -1){
                        builder.append((char) tmp);
                    }
                    System.out.println("received: " + builder.toString());
                }
            } 
            catch(IOException e){
                e.printStackTrace();
            }
        }
    }
}

以下是关于代码的一些总体观点和想法:
  • 正如您所看到的,在主线程中,我只接受一个新连接。一旦客户端连接,我就将连接对象交给线程。然后它开始与客户端通信。
  • 在Java中,我们通常将开括号放在请求语句的同一行,但这只是一个细节,不是必须的。
  • 始终要处理异常或者不要捕获它们。所以最小的处理方式是printStacktrace()或者用"throws xException"声明您的方法,但不要捕获和忽略它们。

下次您在此发布内容时,我建议您包括所有导入语句等,这可以帮助那些试图帮助您的人。(有时候,导入可能是所有问题的根源,例如当某人导入java.awt.List而不是java.util.List时)

希望我能帮到您!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接