Brak odczytu zawartości BufferedReader

Odpowiedz Nowy wątek
2019-08-12 11:46
0

Witam,

Napisłem prosta aplikację na androida, która odbiera z serwera dane (serwer python). O ile komunikacja

Funkcja wysyłająca dana z serwera python (standardowa metoda wysyłajaca dane w komunikacji socketowej):

   tmp="Operation OK"
   send(bytes(tmp,'UTF-8'))

Funkcja odbierająca klienta java:

   public void run() {

            try {
                InetAddress serverAddr =  InetAddress.getByName(SERVER_IP);
                Log.d("ClientActivity", "C: Connecting...");
                socket = new Socket(serverAddr, SERVERPORT);
                connected = true;
                String msg="";
                BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(),StandardCharsets.UTF_8));
                while (connected) {
                    if(arePasswordsEqual(et2.getText().toString(),et3.getText().toString())==true) {
                        Log.d("ClientActivity", "C: Sending command.");
                        String strL = "Test";
                        PrintWriter out = new PrintWriter(new BufferedWriter(
                                new OutputStreamWriter(socket.getOutputStream())),
                                true);
                        out.println(strL);
                        Log.d("ClientActivity", "C: Sent.");
                    }
                    else {}
                    String response ;
                    while ((response = in.readLine()) != null) {
                        Log.d("ClientActivity", "works before" );
                        msg+=response;
                        Log.d("ClientActivity", "works after" );
                    }
                    Log.d("ClientActivity", "Get:" + msg);
                    msg="";
                    connected=false;
                }

                socket.close();
                Log.d("ClientActivity", "C: Closed.");

            } catch (UnknownHostException e) {
                e.printStackTrace();
                connected = false;
            } catch (IOException e) {
                e.printStackTrace();
                connected = false;
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }

        }

Niestety program nie wchodzi do pętli

   while ((response = in.readLine()) != null) 

i nie wiem dlaczego.

edytowany 2x, ostatnio: mariusz198787, 2019-08-12 12:20

Pozostało 580 znaków

2019-08-12 12:46
0

Co to za serwer? Też jakaś twoja apka? Jeśli tak, to pokaż.
Funkcja readLine zwraca NULL kiedy napotka koniec strumienia (EOF). A koniec strumienia następuje kiedy serwer zamyka połączenie.
Przykładowa komunikacja (np. HTTP) w uproszczeniu wygląda tak:

  • serwer nasłuchuje
  • klient rozpoczyna wysyłanie danych do serwera
  • serwer odbiera dane od klienta
  • serwer kończy transmisję klient - serwer
  • serwer wysyła dane do klienta
  • serwer kończy transmisję serwer - klient.

Upewnij się, że serwer zamyka połączenie i nie wysyła pustej linii.

edytowany 1x, ostatnio: PerlMonk, 2019-08-12 12:46

Pozostało 580 znaków

2019-08-12 12:50
0

Kod serwera:

   #!/usr/bin/python           # This is server.py file

import socket               # Import socket module
import pymysql.cursors

def dataBaseOperation(id,login,password):
    try:
        db = pymysql.connect(host="localhost",    # your host, usually localhost
                             user="root",         # your username
                             passwd="pass",  # your password
                             db="tmp")        # name of the data base

        cur = db.cursor()
        cur.execute("insert into uzytkownicy (id,login,password) values ('%s','%s','%s')" %(id,login,password))

        db.commit()
        sendFlag=True
    except:
        db.rollback()
        print('Operation failed.')
        sendFlag=False
    finally:
        if db != None:
            db.close()
    return sendFlag

def main():
    s = socket.socket()         # Create a socket object
    host = socket.gethostname() # Get local machine name
    ip=socket.gethostbyname(host)
    print (ip)
    port = 7777                # Reserve a port for your service.
    s.bind((host, port))        # Bind to the port
    data=''
    s.listen(5)                 # Now wait for client connection.

    while True:
        c, addr = s.accept()     # Establish connection with client.
        fromClient=''
        print('From: ',addr)
        while True:
            data=c.recv(1024) 
            if not data: break
            fromClient+=data.decode().rstrip()
            if fromClient.startswith("Start"):
                data=fromClient.split(";")
                optmp=dataBaseOperation(data[1],data[2],data[3])
                if optmp is True:
                    tmp="Operacja powiodła się"
                    #print(tmp)
                    c.send(bytes(tmp,'UTF-8'))
                    #print(c.send(bytes(tmp,'UTF-8')))
                    tmp=''
                else:
                    tmp="Operacja nie powiodła się"
                    c.send(bytes(tmp,'UTF-8'))
                    tmp=''
    c.close()

if __name__ == "__main__":
    main()

Sprawdzałem while z readline dla warunku ==NULL, ale też tę pętlę omija.

edytowany 1x, ostatnio: mariusz198787, 2019-08-12 12:52

Pozostało 580 znaków

2019-08-12 13:49

Sprawdź jak zachowa się taka pętla:

while (true) {
    response = in.readLine();

    if (response == NULL || response.isEmpty()) {
        break;
    }

    Log.d("ClientActivity", "works before" );
    msg+=response;
    Log.d("ClientActivity", "works after" );
}

Jeśli to nic nie da, sprawdź co się stanie z taką pętlą:

int bufferSize = 4096;
int bytesRead = -1;
char buffer[] = new char[bufferSize];

while (true) {
    Arrays.fill(buffer, 0);
    bytesRead = in.read(buffer);

    if (bytesRead <= 0) {
        System.out.println("Brak danych " + bytesRead);
    }

    Log.d("ClientActivity", "works before" );
    msg += new String(Arrays.copyOfRange(buffer, 0, bytesRead));
    Log.d("ClientActivity", "works after" );
}

Zobaczysz tutaj ile danych jest przesyłanych.

Pozostało 580 znaków

2019-08-12 14:32
0

Dla pierwszego przypadku sytuacja ta sama co poprzednio, ale juz dla drugiego działa ok (zawartość pętli jest osiągalna) i wszystkie dane wysłane przez serwer trafiają do klienta.

Pozostało 580 znaków

2019-08-12 14:49
0

Dopiero zauważyłem, że w drugiej wersji pętli nie dodałem instrukcji break. Ale z tym chyba sobie poradzisz.
Warto zwrócić uwagę, że przy przesyłaniu tekstu w kodowaniu UTF-8 liczba znaków nie musi równać się liczbie bajtów.

Pozostało 580 znaków

2019-08-12 15:04
0

Tak, poradze sobie. Dzięki za pomoc. Jednak nadal nie rozumiem dlaczego to nie działało

   while ((response = in.readLine()) != null) {
edytowany 1x, ostatnio: mariusz198787, 2019-08-12 15:04

Pozostało 580 znaków

2019-08-12 15:47
0

Z tego, co rozumiem z kodu serwera

if not data: break

jeśli nie odczyta danych, kończy pętlę i nie wysyła nic klientowi. Klient wtedy dostanie null. W trybie nieblokującym normalnie wygenerowałbyś nowe zdarzenie w takiej sytuacji zamiast czekać uparcie, że coś tam będzie.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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

Użytkownik: mariusz198787