Помогите разобраться с Socket, ServerSocket

309
03 ноября 2017, 08:57

Есть код:

import java.io.*;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class FirstSocket {
    public static void main(String[] args) {
        try (Socket socket = new Socket()){
            socket.connect(new InetSocketAddress("localhost", 2111), 2000);
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String str;
            while ((str = bufferedReader.readLine()) != null)
                System.out.println(str);
            PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true);
            printWriter.write("Привет тебе из сокета, друг!");
            bufferedReader.close();
            printWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
class ServerRun{
    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(2111)){
            while (true){
                Socket socket = serverSocket.accept();
                new Thread(new MyServer(socket)).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class MyServer implements Runnable{
    private Socket socket;
    public MyServer(Socket socket){
        this.socket = socket;
    }
    @Override
    public void run() {
        try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
             PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true)){
            String str;
            while ((str = bufferedReader.readLine()) != null)
                System.out.println(str);
            printWriter.write("А тебе привет из сервера!\n");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Проблема в том, что когда я запускаю сервер, а затем сокет программа виснет. Если остановить вручную, то ругается на строчку у сервера:

while ((str = bufferedReader.readLine()) != null) 

И выдаёт:

java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:210)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.readLine(BufferedReader.java:324)
at java.io.BufferedReader.readLine(BufferedReader.java:389)

Если убрать у сервера возможность читать сообщения от клиента, то всё работает нормально. Пробовал читать через ObjectOutputStream, Scanner такой же результат

Answer 1

Первое. У Вас взаимная блокировка. Так как клиент ожидает данные от сервера и сервер от клиента.

Второе. В случае, когда Вы читаете строки из потока, поток вернет пустую строку, когда будет закрыт сокет или исходящий поток, на другой стороне подключения. Цикл:

while ((str = bufferedReader.readLine()) != null)
   System.out.println(str);

выход из цикла произойдет, когда другая сторона закроет соединение или исходящий поток.

Поробуйте произвести единичную запись без цикла и чтение.

Сервер:

System.out.println(bufferedReader.readLine());
printWriter.write("А тебе привет из сервера!\n");

Клиент:

printWriter.write("Привет тебе из сокета, друг!\n");
System.out.println(bufferedReader.readLine());

или наоборот

Код моего решения:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class Client extends Thread {
    @Override
    public void run() {
        System.out.println("Client start");
        try(Socket socket = new Socket()) {
            socket.connect(new InetSocketAddress("localhost", 2111), 2000);
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true);
            printWriter.println("Привет тебе из сокета, друг!");
            System.out.println("C: " + bufferedReader.readLine());
        } catch(IOException e) {
            e.printStackTrace();
        }
    }
}
public class Server extends Thread {
    public static void main(String...args) {
        new Server().start();
    }
    @Override
    public void run() {
        try (ServerSocket serverSocket = new ServerSocket(2111)){
            //запуск клиента, после запуска сервера
            new Client().start();
            while (true){
                Socket socket = serverSocket.accept();
                System.out.println("accept");
                new ServerClient(socket).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public class ServerClient extends Thread {
        public final Socket client;
        public ServerClient(Socket client) {
            this.client = client;
        }
        @Override
        public void run() {
            System.out.println("ServerClient start");
            try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(client.getInputStream()));
                    PrintWriter printWriter = new PrintWriter(client.getOutputStream(), true)){
                   System.out.println("S: " + bufferedReader.readLine());
                   printWriter.println("А тебе привет из сервера!");
               } catch (IOException e) {
                   e.printStackTrace();
               }
        }
    }   
}

Результат работы программы:

Client start
accept
ServerClient start
S: Привет тебе из сокета, друг!
C: А тебе привет из сервера!
Answer 2
Да не вопрос:
import java.net.*;
import java.io.*;
public class Client {
    public static void main(String[] ar) {
        int serverPort = 2111; 
        String address = "127.0.0.1"; 
        try {
            Socket socket = new Socket(InetAddress.getByName(address), serverPort); 
            DataInputStream in = new DataInputStream(socket.getInputStream());
            DataOutputStream out = new DataOutputStream(socket.getOutputStream());
            BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in));
            String line;
            while (true) {
                line = keyboard.readLine(); 
                System.out.println("Client: " + line);
                out.writeUTF(line); 
                out.flush(); 
                line = in.readUTF(); 
                System.out.println("Server : " + line);
            }
        } catch (IOException e) {
            System.out.println("Exception : " + e);
        }
    }
}
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
   public static void main(String[] arg) {
     int port = 2111; 
       try {
         ServerSocket ss = new ServerSocket(port);
         Socket socket = ss.accept();
         DataInputStream in = new DataInputStream(socket.getInputStream());
         DataOutputStream out = new DataOutputStream(socket.getOutputStream());
         String line;
         while(true) {
           line = in.readUTF(); 
           System.out.println("Client : " + line);
           out.writeUTF("Привет тебе из сокета, друг!");
           out.flush(); 
         }
      } catch(IOException e) {
          System.out.println("Exception : " + e);
      }
   }
}
READ ALSO
Кастомный fontFamily

Кастомный fontFamily

Если у TextView в API > 16 задать

236
Взаимодействие java и html5

Взаимодействие java и html5

Нужно поставить обработчиком кода метод из javaJavascrypt не поможет

301
Как правильно сделать запрос по условию с датой к БД в Java (JDBC)

Как правильно сделать запрос по условию с датой к БД в Java (JDBC)

Вопрос состоит в том что я хочу правильно оформить запрос, да бы не допустить в будущем SQL-инъекций но что-то не получается, помогите разобраться,...

315