TCP / Sockets клиент / сервер - сервер отвечает только на первое соединение от клиента - PullRequest
0 голосов
/ 21 октября 2018

У меня есть некоторый простой код клиента и сервера, где клиент отправляет несколько байтов на сервер, а сервер отвечает несколькими байтами.Клиент печатает полученные байты, а затем закрывает сокет.

Это прекрасно работает при первом запуске клиента, но последующие вызовы не получают ответа.

package sockets.com;

// Client Side
import java.io.*;
import java.net.*;

public class ClientSideTCPSocket {
    public void run() {
        try {
            int serverPort = 4023;
            InetAddress host = InetAddress.getByName("localhost");

            System.out.println("Connecting to server on port " + serverPort);

            Socket socket = new Socket(host, serverPort);

            System.out.println("Just connected to " + socket.getRemoteSocketAddress());


            OutputStream out = socket.getOutputStream();
            InputStream in = socket.getInputStream();

            String s = "HELLO SERVER";
            byte[] bytes = s.getBytes("US-ASCII");

            for (byte b : bytes) {

                out.write(b);

            }

            int ch = 0;
            while ((ch = in.read()) >= 0) {

                System.out.println("Got byte " + ch);
            }

            out.flush();
            out.close();

            socket.close();

        } catch (UnknownHostException ex) {
            ex.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        ClientSideTCPSocket client = new ClientSideTCPSocket();
        client.run();
    }
}

Код сервера

package sockets.com;

//Server Side
import java.net.*;
import java.io.*;

public class ServerSideTCPSocket {
    public void run() {
        try {
            int serverPort = 4023;
            ServerSocket serverSocket = new ServerSocket(serverPort);
            serverSocket.setSoTimeout(900000);
            while (true) {
                System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");

                Socket server = serverSocket.accept();
                System.out.println("Just connected to " + server.getRemoteSocketAddress());

                //
                int ch = 0;
                while ((ch = server.getInputStream().read()) >= 0) {

                    System.out.println("Got byte " + ch);
                }
                // Write to output stream

                OutputStream out = server.getOutputStream();

                String s = "HELLO CLIENT";
                byte[] bytes = s.getBytes("US-ASCII");

                for (byte b : bytes) {
                    System.out.println(b);

                    out.write(b);

                }

            }
        } catch (UnknownHostException ex) {

            ex.printStackTrace();
        } catch (IOException e) {

            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        ServerSideTCPSocket srv = new ServerSideTCPSocket();
        srv.run();
    }

}

Буду признателен за любые комментарии относительно того, почему это так.Спасибо.

1 Ответ

0 голосов
/ 21 октября 2018

Несколько вещей:

Этот блок кода будет зацикливаться до тех пор, пока клиент не закроет свое соединение:

            while ((ch = server.getInputStream().read()) >= 0) {

                System.out.println("Got byte " + ch);
            }

Затем, после того как клиент закроет свое соединение, последующая попытка отправки«HELLO CLIENT» для сокета сгенерирует исключение ввода-вывода.Это заставит ваш серверный цикл завершиться.

Простое решение состоит в том, чтобы настроить ваш протокол так, чтобы "сообщение" было завершено на некотором символе часового.В моем простом исправлении я просто настроил его так, чтобы он срабатывал при получении !.

Лучше, чтобы каждый сеанс клиента завершался на исключении ioexception вместо всего блока сервера.Мой рефакторинг вашего кода:

public class ServerSideTCPSocket {

    public void tryCloseSocketConnection(Socket socket) {
        try {
            socket.close();
        }
        catch(java.io.IOException ex) {
        }
    }

    public void processClientConnection (Socket clientConnection) throws java.io.IOException {

        int ch = 0;
        while ((ch = clientConnection.getInputStream().read()) >= 0) {

            System.out.println("Got byte " + ch);
            if (ch == '!') {
                break;
            }
        }
        // Write to output stream

        OutputStream out = clientConnection.getOutputStream();

        String s = "HELLO CLIENT!";
        byte[] bytes = s.getBytes("US-ASCII");

        for (byte b : bytes) {
            System.out.println(b);
            out.write(b);
        }
    }

    public void run() {
        try {
            int serverPort = 4023;
            ServerSocket serverSocket = new ServerSocket(serverPort);
            serverSocket.setSoTimeout(900000);
            while (true) {
                System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");

                Socket clientConnection = serverSocket.accept();

                try {
                    System.out.println("Just connected to " + clientConnection.getRemoteSocketAddress());
                    processClientConnection(clientConnection);
                }
                catch (java.io.IOException ex) {
                    System.out.println("Socket connection error - terminating connection");
                }
                finally {
                    tryCloseSocketConnection(clientConnection);
                }
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        ServerSideTCPSocket srv = new ServerSideTCPSocket();
        srv.run();
    }
}

Затем настройте сообщение вашего кода клиента так:

        String s = "HELLO SERVER!";  // the exclamation point indicates "end of message".
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...