Serwer na PC i Klient na Android - brak połączenia

0

Witam

Napisałem prosty program serwera który działałby na moim komputerze oraz program klienta na telefonie z systemem Android. Niestety nie mogę uzyskać połączenia ze swoim komputerem. Aplikacja na Adroid działa, jeśli wpiszę inny adres IP lub nazwę np. "time-a.nist.gov 13" wysyłając takie żądanie połączenia do serwera aplikacja otrzymuje informację zwrotoną o aktulanie panującym czasie. Próbowałem wyłączać antywirusa i firewalla i też nic nie pomaga. Jeżeli łącze się z serwerem przez telnet z poziomu komputera to serwer też odpowiada. Także wychodzi na to, że dwa programy działają ale Android z komputerem nie chcą się skomunikować. Dodam, że to pliku manifestu dodałem <uses-permission android:name="android.permission.INTERNET" />
Jestem początkującym w programowaniu na Android, także możliwe, że jest gdzieś głupi błąd ale ja go nie widzę. Istnieją podobne tematy w sieci, ale rozwiązaniem jest naprawa jakiegoś błędu w kodzie. Zweryfikowałem kod i ja takich błedów nie posiadam a komunikacja nadal nie działa. Bardzo proszę o pomoc.

Kod serwera na pc:


class ClientRequest extends Thread {
    private static int count = 0;
    private int id = count++;
    private String clientName;
    private Socket socket;
    private Scanner scanner;
    private PrintWriter printWriter;
    public ClientRequest(Socket socket) throws IOException {
        this.socket = socket;
        clientName = "CL " + count;
        super.setName(clientName);
        scanner = new Scanner(this.socket.getInputStream());
        printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()),true);
    }
    @Override public void run() {
        printWriter.println("Wpisz komende. Exit konczy!");
        String command = scanner.next();
        while(!command.equals("Exit")) {
            switch(command) {
                case "imie":
                    printWriter.println("Kuba");
                    break;
                case "wiek":
                    printWriter.println("20");
                    break;
                default:
                    printWriter.println("Nieznana komenda!");
            }
            command = scanner.next();
        }
        try {
            scanner.close();
            printWriter.close();
            socket.close();
        }
        catch(IOException e) {}
        System.out.println("Klient: " + clientName + " konczy!");
    }
}

public class MojServer {


    public static void main(String[] args) throws IOException {
        
      
        ArrayList<Thread> threads = new ArrayList<>();
        //String addrServerString = "127.0.0.1";
        String addrServerString = "192.168.56.1";
        InetAddress addrServer = InetAddress.getByName(addrServerString);
        try (ServerSocket s = new ServerSocket(8180,50,addrServer))
        { 
          System.out.println("Adres servera:" + s.getLocalSocketAddress() + "\nOczekiwanie klientow..."); 
       
         int i = 1;
         ExecutorService exec = Executors.newCachedThreadPool();
         while (true)
         {  
            for(Thread T : threads) {
                System.out.println(T.getName() + " Alive?: " + T.isAlive());
            }
            Socket incoming = s.accept();
            System.out.println("Spawning " + i);
            Thread r = new ClientRequest(incoming);
            exec.execute(r);
            i++;
         }
      }
      catch (IOException e)
      {  
         e.printStackTrace();
      }
        
        
    }
    
}

A poniżej kod klienta na telefonie: ( pomijam już klasę main i inne szczegóły - poniżej kod aktywności która odpowiedzialna jest za połączenie )
Aplikacja działa tak, że w tle wątek łączy mnie z komputerem - po połączeniu otrzymuję komunikat powitalny. A w EditText wpisuję odpowiednie komendy, wciskam przycisk wyślij, a serwer odsyła mi odpowiedź, którą widzę w TextView.



class Counter {
    public volatile int counter = 0;
}

class ConnectTask extends Thread {
    private String serverIP;
    private int serverPort;
    private Scanner scanner;
    private PrintWriter writer;
    private LinkedBlockingDeque<String> sendQueue;
    private LinkedBlockingDeque<String> reciveQueue;
    private Socket socket;
    private Counter counter;
    public ConnectTask(Socket socket, String serverIP, int serverPort,
                       LinkedBlockingDeque<String> sendQueue,LinkedBlockingDeque<String> reciveQueue, Counter counter) {
        this.serverIP = serverIP;
        this.serverPort = serverPort;
        this.socket = socket;
        this.sendQueue = sendQueue;
        this.reciveQueue = reciveQueue;
        this.counter = counter;
    }
    @Override public void run()  {
        try {
            socket.connect(new InetSocketAddress(serverIP,serverPort));
            scanner = new Scanner(socket.getInputStream());
            writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
            try {
                while (!Thread.interrupted()) {
                    if(scanner.hasNextLine())
                        reciveQueue.put(scanner.nextLine());
                    String text = sendQueue.poll();
                    if(text != null)
                        writer.write(text);
                    counter.counter++;
                }
            }
            catch (InterruptedException e) {
                Thread.interrupted(); //zasyngalizowanie na zewnatrz ze watek zostal przerwany
            }
            scanner.close();
            socket.close();
        }
        catch (IOException e) {

        }

    }
}

public class connectPage extends AppCompatActivity {

    private LinkedBlockingDeque<String> toSend = new LinkedBlockingDeque<>();
    private LinkedBlockingDeque<String> toReciv = new LinkedBlockingDeque<>();
    private Counter counter = new Counter();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_connect_page);


        //String ipServerAddres = "192.168.1.109";
        String ipServerAddres = "Jakub-Komputer"; //poprzez nazwę komunikacja również działa z serwerem wykorzystując telnet na PC, poprzez aplikację nie działa
        int serverPort = 8180;
        Socket socket = new Socket();

        ConnectTask connectTask = new ConnectTask(socket,ipServerAddres,serverPort,toSend,toReciv,counter);

        final Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            TextView counterView = (TextView)findViewById(R.id.counterTextView);
            @Override
            public void run() {

                if(!toReciv.isEmpty()) {
                    ((TextView)findViewById(R.id.receiveMassageWindow)).setText(toReciv.poll());
                }
                counterView.setText(String.valueOf(counter.counter));
                handler.postDelayed(this,500);
            }
        },500);

        connectTask.start();

    }

    public void clearEditTextBox(View view) {
        EditText editText = (EditText)this.findViewById(R.id.insertTextWindow);
        editText.setText("");
    }

    public void sendCmdToServer(View view) {
        EditText editText = (EditText)this.findViewById(R.id.insertTextWindow);
        toSend.add(editText.getText().toString());

    }

}

2

bo nie masz https: musisz albo wylaczyc uzywanie https albo zainstalwoac certyfikat

0
masterO napisał(a):

bo nie masz https: musisz albo wylaczyc uzywanie https albo zainstalwoac certyfikat

W sensie muszę to zrobić na telefonie? Jakaś podpowiedź jak to zrobić?

0

Jak pisalem na iOSa to musialem w glownym ustawieniu programu ktory pisalem dodac dyrektywe ze zgadzam sie na nieuzywanie https. ALe jak to zrobic na androidzie to nie wiem. zerknij tu https://stackoverflow.com/questions/2012497/accepting-https-connections-with-self-signed-certificates

1

HTTPS i Android nie mają tutaj znaczenia. Jeżeli napisałbyś taką samą aplikację konsolową, to też by nie działała. Blokujesz sobie wątki skanerami, do których nic nie wysyłasz i wiszą.

0
Michał Sikora napisał(a):

HTTPS i Android nie mają tutaj znaczenia. Jeżeli napisałbyś taką samą aplikację konsolową, to też by nie działała. Blokujesz sobie wątki skanerami, do których nic nie wysyłasz i wiszą.

Ale tak jak napisałem w pierwszym poście: aplikacja łączy się przykładową podanym przeze mnie adresem serwera, który zwraca czas atomowy. Wygląda na to, że działa. Masz rację blokowanie jest ale na Socket:

 socket.connect(new InetSocketAddress(serverIP,serverPort));

Ponieważ socket nie jest w stanie utworzyć połączenia z serwerem, który działa cały czas u mnie na PC. I tego nie mogę zrozumieć. Podaje poprawny port i adres IP i nie działa. Również nie działa z adresem 127.0.0.1

0

U mnie ten kod normalnie się łączy z lokalnym serwerem z moim IP zarówno na telefonie jak i emulatorze.

0

Kurcze to obawiam się, że mam coś z systemem. Np. swingowe aplikacje z jara też mi się nie odpalają a na innym komputerze wszystko chodzi :/ Coś musiało się popsuć, ale czegoś nie mam skonfigurowanego. A czy może być to też jakaś wada rutera? Jest dość stary...

0

Jeśli łączysz się z telefonu poprzez router, to nie sądzę. Spinguj swój komputer z telefonu, to zobaczysz, czy masz połączenie.

0
Michał Sikora napisał(a):

HTTPS i Android nie mają tutaj znaczenia. Jeżeli napisałbyś taką samą aplikację konsolową, to też by nie działała. Blokujesz sobie wątki skanerami, do których nic nie wysyłasz i wiszą.

Okej, jakoś się z tym uporałem. Nie wiem czemu nie działało, po prostu nagle zaczęło działać - spodziewam się, że jakiś problem z ruterem, może zasięgu nie łapie, chociaż na telefonie są kreski...
Masz racje, coś tutaj blokuje ponieważ mogę otrzymywać tekst, ale nie mogę go wysyłać. Ale nie rozumiem dlaczego wątek jest zablokowany.
Wciśnięciem przycisku umieszczam wpisane dane w EditView w kolejce:

 public void sendCmdToServer(View view) {
        EditText editText = (EditText)this.findViewById(R.id.insertTextWindow);
        toSend.add(editText.getText().toString());
    }

Metoda run() wątku wysyłającego i odbierającego najpierw sprawdza, czy w kolejce toSend, są jakieś dane, jeżeli tak to wysyła je poprzez strumień writer. Natomiast jeśli chodzi o dane odbierane to scaner najpierw sprawdza w warunku if czy są jakieś dane do odbioru zanim zostanie wywołana blokująca metoda nextLine().

  @Override public void run()  {
        try {
            socket.connect(new InetSocketAddress(serverIP,serverPort));
            scanner = new Scanner(socket.getInputStream());
            writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
            try {
                while (!Thread.interrupted()) {
                    if(scanner.hasNextLine())
                        reciveQueue.put(scanner.nextLine());
                    counter.counter++;
                    String text = sendQueue.poll();
                    if(text != null)
                        writer.write(text);
                    counter.counter++;
                }
            }
            catch (InterruptedException e) {
                Thread.interrupted(); //zasyngalizowanie na zewnatrz ze watek zostal przerwany
            }
            scanner.close();
            writer.close();
            socket.close();
        }
        catch (IOException e) {

        }

    }

Teraz jak czytam w dokumentacji do hasNextLine():
"Returns true if there is another line in the input of this scanner. This method may block while waiting for input. The scanner does not advance past any input."
To widzę, że ta metoda też może blokować. Jak hasNext() i next() blokują to jak to rozwiązać? Przenieś odczyt do jeszcze innego wątku?

1 użytkowników online, w tym zalogowanych: 0, gości: 1