2013-02-11 17 views
8

Buduję prosty serwer Java Bluetooth dla mojego komputera za pomocą interfejsu API Bluecove. Buduję również aplikację dla klienta Android, ale problem wydaje się wynikać z aplikacji po stronie serwera.Utrzymywanie połączenia Java Bluetooth

Jestem pewien, że ktoś opublikował już gdzieś jakąś odpowiedź, a ja od kilku dni starannie testowałem różne rozwiązania i patrzyłem na każde możliwe forum, ale nie mogę utrzymać połączenia w wątku gniazda przy życiu.

Mogę wymieniać wiadomości po nawiązaniu połączenia z androida na komputer i odwrotnie z komputera na androida, ale natychmiast po wymianie bajtów, stos Bluecove wyłącza się i zamyka połączenie z gniazdem, nawet gdy nie jawnie powiedz to do connection.close().

Próbowałem użyć krótkiego czasu (niektóre stwierdzenie jest prawdą), aby utrzymać połączenie przy życiu i nie wyłącza już gniazda po otrzymaniu pierwszej wiadomości, ale nie może odbierać żadnych kolejnych wiadomości wysyłanych przeze mnie smartfona do mojego komputera. Choć zasadniczo jest żywy, nie może odbierać żadnych nowych wiadomości, gdy próbuję wysłać je ze smartfonu. Nie pewny dlaczego.

Przykro mi, to jest moja pierwsza publikacja i nie jestem pewien, dlaczego pierwsza część kodu nie wyświetla się poprawnie na stronie.

Kod dokonywania gra:

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) {} 
} 

GWINT KOD do słuchania Napływające dane

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){} 
} 
+0

Nie można wysłać więcej niż jednej wiadomości od klienta do serwera, ale czy można wysyłać wiele wiadomości z serwera do klienta? Która pętla wywołuje twoją metodę run()? Czy możesz podać ten kod, wywołując funkcję run()? –

+0

W przeszłości mam bardzo podobny problem. Ale w moim przypadku połączenie nie zostało zamknięte, tylko prędkość IO zwalniała (po stronie Androida). Po debugowaniu odkryliśmy, że po pewnym okresie bezczynności zdarza się on po stronie Androida po określonym czasie oczekiwania (Android przełącza tryb bezpiecznego zasilania) i tego limitu czasu nie można zmienić. Aby utrzymać połączenie przy życiu, po prostu wysyłaliśmy okresowo pusty pakiet (jeden bajt). Mam nadzieję, że to pomoże. – Eugene

+0

Nie używaj tylko pustych bloków try/catch. Zaloguj wyjątek, gdy zostanie rzucony, pomoże ci uzyskać prawdziwy powód. W przeciwnym razie zgadujesz. – Don

Odpowiedz

0

Niestety nie mogę wypróbować swój kod na moim komputerze w czasie rzeczywistym, ale myślę, że widziałem swój błąd : in your run() - Metoda odczytana ze strumienia wejściowego, wydrukowana na konsoli, a następnie zakończona. Po ostatniej linii należy wykonać polecenie run() - metoda została zakończona, a wątek zostanie odrzucony przez środowisko wykonawcze. Będziesz musiał umieścić odbiór na chwilę (true) lub podczas (bieżącej) pętli.

Zmodyfikowałem twój kod i oto jest, jednak pamiętaj o tym, co powiedziałem wcześniej: nie mogłem go przetestować, więc jest całkowicie nieprzetestowany!

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(); 
      } 
     } 
    } 
} 

Oto kilka ogólnych punktów i myśli o kopalni i kodzie:

  • Jak widać, w głównym wątku Ja tylko przyjąć nowe połączenie. Zaraz po podłączeniu klienta podaję obiekt połączenia do wątku. Następnie zaczyna komunikować się z klientem
  • W Javie zwykle umieszczamy nawiasy otwierające w tej samej linii, co instrukcja, która o to prosi, ale jest to tylko szczegół i nie jest koniecznością.
  • ZAWSZE rób coś z wyjątkami lub nie łapaj ich. Zatem minimum to printStacktrace() lub zadeklaruj swoją metodę za pomocą "throws xException", ale nie łapaj i ignoruj ​​ich.

Następnym razem, gdy coś publikujesz, polecam dołączenie wszystkich instrukcji importowania itp., Może pomóc osobom, które próbują ci pomóc. (czasami import może być przyczyną wszystkich problemów, na przykład gdy ktoś zaimportował plik java.awt.List zamiast java.util.List)

Mam nadzieję, że ci pomogłem!

Powiązane problemy