NOVINKA! E-learningové kurzy umělé inteligence. Nyní AI za nejlepší ceny. Zjisti více:
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Diskuze: Problém s kódováním server-klient

V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Neaktivní uživatel:29.7.2016 13:55

Ahojte, splácal jsem primitivní klient a server. Klient se připojí k serveru (na localhostu) a posílá zprávy, které zadá uživatel. Problém nastává při posílání textu s diakritikou: Klient i server je spuštěný každý v instanci CMD / powershell (zkoušel jsem obojí). před spuštěním zadám příkaz "chcp 65001", což má změnit code page na Unicode při použití UTF-8. Všechny streamy, které v klientu a serveru zapisují, jsou Buffered Streamy s explicitně nastaveným UTF-8 kódováním. Stejně při odeslání textu, co obsahuje diakritiku, není stream reader schopný načíst text, a String, kam si to ukládám, je null. Zkoušel jsem snad všemožné kombinace např. se Scannerem, nic nefunguje. Buď stream nic nepřečte a vrátí null, nebo se na serveru zpráva zobrazí špatně. Něco důležitého mi tu uniká. Nemohl by mi někdo pomoct?

Tady je Klient:

import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;


public class Client
{
        public static void main(String[] args) throws Exception
        {
                BufferedReader input = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8));
                BufferedWriter output = new BufferedWriter(new OutputStreamWriter(System.out, StandardCharsets.UTF_8));
                output.write("Press enter to connect");
                output.flush();
                input.readLine();

                Socket clientSocket = new Socket("localhost", 5000);

                output.write("Connected to server\n");
                output.flush();

                BufferedWriter senderWriter = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream(), StandardCharsets.UTF_8));
                String message = "";
                while(!message.equals("--disconnect"))
                {
                                output.write("Type message: ");
                                output.flush();

                                //Pokud String vytvořím v programu, na Serveru se zobrazí správně:
                                // String s = "český textík s řádnou diakritikou";
                                // sendWriter.write(s);

                                //ZDE - funkce vrací null, pokud do cmd/powershell napíšu znak s diakritikou a odešlu enterem
                                // program následně spadne u zápisu message s NullPointerException
                                message = input.readLine();
                                //_______________________________________

                                senderWriter.write(message);
                                senderWriter.newLine();
                                senderWriter.flush();
                }
                System.out.println("You have disconnected from the server");
        }
}

Tady je server:

import java.net.*;
import java.nio.charset.StandardCharsets;
import java.io.*;


public class Server
{

        public static void main(String[] args) throws Exception
        {
                ServerSocket serverSocket = new ServerSocket(5000);
                Socket clientSocket = serverSocket.accept();

                System.out.println("Client connected from address " + clientSocket.getLocalAddress().getHostAddress() + " under port " + Integer.toString(clientSocket.getLocalPort()));

                BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), StandardCharsets.UTF_8));
                BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(System.out, StandardCharsets.UTF_8));

                String message = "";
                int mes = 0;
                while(!(message = br.readLine()).equals("--disconnect"))
                {
                        wr.write("Client sends a message:" + message + "\n");
                        wr.flush();
                }

                System.out.println("Client disconnected!");

                clientSocket.close();
        }
}
Odpovědět
29.7.2016 13:55
Neaktivní uživatelský účet
Avatar
Petr Štechmüller:29.7.2016 17:24

Ahoj, problém je v příkazové řádce woken, že má výchozí znakovou sadu cp1250.
Místo scanneru, nebo buffered readeru použij objekt Console.

Zde je použití:

// Získání instance
private static Console console = System.console();

// Vypsání textu
console.printf("Connected to server\n");

// Získání textu
message = console.readLine();
Nahoru Odpovědět
29.7.2016 17:24
Pokud spolu kód a komentář nekorespondují, budou patrně oba chybné
Avatar
Odpovídá na Petr Štechmüller
Neaktivní uživatel:29.7.2016 20:24

Jop, právě proto sadu přepínám jak u klienta tak u serveru - "chcp 65001". Console problém neřeší, readLine vrátí stejně null. Nicméně alespoň funguje, když nechám právě výchozí code page 1250 (což BufferedReader ani Scanner nedokázal). Takže alespoň to dokáže komunikovat jazyky, pro které je 1250 dělaná, když už ne globálně Unicode :-)

Nahoru Odpovědět
29.7.2016 20:24
Neaktivní uživatelský účet
Avatar
Odpovídá na Neaktivní uživatel
Petr Štechmüller:29.7.2016 20:26

Tak to je divný, me to funguje parádně.

Editováno 29.7.2016 20:26
Nahoru Odpovědět
29.7.2016 20:26
Pokud spolu kód a komentář nekorespondují, budou patrně oba chybné
Avatar
Odpovídá na Petr Štechmüller
Neaktivní uživatel:29.7.2016 20:28

Máš anglickou verzi Windows nebo českou? Já mám anglickou verzi a přepínam jenom na českou klávesnici. Ale nenapadá mě, proč by to na to mělo mít vliv, když tu code page stejně přenastavuju. Možná jak Win zachází s klávesnicí?? Nwm.

Nahoru Odpovědět
29.7.2016 20:28
Neaktivní uživatelský účet
Avatar
Odpovídá na Neaktivní uživatel
Petr Štechmüller:29.7.2016 20:29

Ja mám českou verzi. Možná to může mít nějaký vliv...

Nahoru Odpovědět
29.7.2016 20:29
Pokud spolu kód a komentář nekorespondují, budou patrně oba chybné
Avatar
pocitac770
Tvůrce
Avatar
pocitac770:30.7.2016 0:22

Pokud by nic nepomáhalo, je tu jistý... Způsob, jak to vyřešit :D
Napadlo mě to jednou použít při komunikaci MC klient - Android app (takže nezávisle na tom, co jste zatím popsali ohledně pouitých "konzolí"), stačí si každý posílaný znak převést na jeho UNICODE číselnou hodnotu, tu odeslat, poté na straně klienta zase převést zpět, sice to zvyšuje datový přenos, ale mělo by to fungovat vždy

Editováno 30.7.2016 0:22
 
Nahoru Odpovědět
30.7.2016 0:22
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 7 zpráv z 7.