Wątek przeniesiony 2017-12-14 10:02 z Java przez somekind.

Klient/server problem z przesyłaniem JSON

0

Mam serwer:

import com.google.gson.Gson;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
 
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.*;
 
public class Server {
 
    private static ServerSocket listener = null;
    private static Socket socket = null;
    private static Gson gson = null;
    private static Connection conn = null;
    private static Statement stmt = null;
    private static ResultSet rs = null;
    private static PreparedStatement preparedStatement = null;
    private static Boolean isInDb = false;
 
    public static void main(String[] args) {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver").newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
        try {
            listener = new ServerSocket(9090);
            gson = new Gson();
 
            while (true) {
                socket = listener.accept();
                try {
                    BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
 
                    JsonReader reader = new JsonReader(in);
                    JsonWriter writer = new JsonWriter(out);
                    String fromJson = null;
 
                    try{
                        if (socket.isConnected()){
                            conn = DriverManager.getConnection("jdbc:mysql://localhost/kino", "root", "");
                        }
 
                        fromJson = gson.fromJson(reader, String.class);
                        String[] data = fromJson.split(":");
 
                        String selectSQL = "SELECT k.login, k.haslo FROM klienci k WHERE k.email = ? AND k.haslo = ?";
                        if (!conn.isClosed()){
                            preparedStatement = conn.prepareStatement(selectSQL);
                            preparedStatement.setString(1, data[0]);
                            preparedStatement.setString(2, data[1]);
 
                            rs = preparedStatement.executeQuery();
 
                            if (rs.next())
                                isInDb = true;
                           
                            gson.toJson(isInDb, Boolean.class, writer);
                        }
                    }catch (SQLException sqle){
                        System.out.println("SQLException: " + sqle.getMessage());
                        System.out.println("SQLState: " + sqle.getSQLState());
                        System.out.println("VendorError: " + sqle.getErrorCode());
                    }
                }finally {
                    socket.close();
                }
            }
        }catch (IOException e){
            System.out.println(e.getMessage());
            System.exit(-1);
        }finally {
            try{
                if (listener != null)
                    listener.close();
            }catch (IOException e){
                System.out.println(e.getMessage());
                System.exit(-1);
            }
        }
    }
}

I klienta:

   @Override
        protected Boolean doInBackground(Void... params) {
            // TODO: attempt authentication against a network service.
            String data = mEmail + ':' + mPassword;
            Gson gson = new Gson();
 
            try {
                Socket socket = new Socket("10.0.2.2", 9090);
                BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
 
                JsonReader reader = new JsonReader(in);
                JsonWriter writer = new JsonWriter(out);
 
 
                gson.toJson(data, String.class, writer);
 
                Boolean isInDb = gson.fromJson(reader, Boolean.class);
 
                if (isInDb){
                    return true;
                }else{
                    Intent intent = new Intent(getApplicationContext(), ChooseSeat.class);
                    startActivity(intent);
                }
 
            }catch (IOException ioe){
                ioe.printStackTrace();
            }
            // TODO: register the new account here.
            return false;
        }
 

Klient(komórka) wysyła login i hasło, serwer sprawdza w bazie i odsyła info tak/nie. Problem polega na tym, że dochodzi tutaj chyba do zakleszczenia, a ja nie za bardzo wiem jak to rozwiązać. Apka na komórce wciąż kręci kółeczkiem, a w serwerze nie ma nic w Stringu fromJson Teoretycznie wiem, że można jakoś REST`em to załatwić, ale nie chce się w to pchać na razie no i chce tylko to jedno zrobić, czyli sprawdzić w bazie. Może ktoś z was ma jakiś pomysł? sleep nie pomógł.

0

W kliencie nie łączysz się z socketem, brakuje socket.connect()

Po sparsowaniu danych do JSON'a musisz je jeszcze wysłać, a że JsonWriter(Writer) może przyjąć tylko writer, a później nasz BufferedWriter nie może wysłać czegoś innego niż tekst to
utworzyłem coś takiego w celu buforowania.

PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);

JsonReader reader = new JsonReader(in);
JsonWriter writer = new JsonWriter(out);

gson.toJson(data, String.class, writer);

out.println(writer);

I ja coś takiego wyczarowałem na szybko, możesz się u siebie upewnić jak to jest z adresami:

try {

		try {
			InetSocketAddress isa = new InetSocketAddress("localhost", 9090);
			listener = new ServerSocket();
			listener.bind(isa);
			gson = new Gson();

			while (true) {
				System.out.println("Server started");
			    System.out.println("at port: " + listener.getLocalPort());
			    System.out.println("bind address: " + listener.getInetAddress());

				socket = listener.accept();
				try {
					System.out.println("Server przyjal polaczenie");

// reszta kodu
0

@pedegie: jedyne co trzeba bylo zrobić to dodać writer.flush() I działa mój kod

1

A widzisz, nie pamiętałem, że jak podasz argumenty w konstruktorze to od razu się połączy. Stosując InetAddress możesz odroczyć / odseparować łączenie z serwerem od tworzenia gniazda. No i jeśli to ma się jakoś skalować to oprócz pul wątków obsługujących żądania, kanały powinny być nieblokujące, wtedy możliwe jest ich multipleksowanie czyli obsługa wielu połączeń na jednym wątku przez selektory. Jak jesteś zainteresowany to zerknij na SelectableChannel Selector i SelectionKey.

0

Odbiegając od tematu (nie wczytywałem się dokładnie), to nie rozumiem po co sie katować obsługą json-a w taki sposób. Zakładam, że serwer to zwykły webserwis restowy, więc nie rozumiem po co uprawiać tu takie akrobacje, zamiast użyć po prostu Retrofita i ewentualnie RxJava.

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