java.net.SocketException: программное обеспечение вызвало прерывание соединения: ошибка записи в сокет при повторной отправке запроса - PullRequest
0 голосов
/ 20 сентября 2018

работа с сокетами по этой проблеме.Я написал реализацию Http и TCP серверов.HTTP работает полностью корректно, поэтому я могу отправлять запросы на сервер один за другим.Что нельзя сказать о TCP-сервере, первый запрос уходит и обрабатывается правильно, но при попытке отправить следующий запрос выдает это исключение:

java.net.SocketException: Software caused connection abort: socket write error
    at java.net.SocketOutputStream.socketWrite0(Native Method)
    at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
    at java.net.SocketOutputStream.write(SocketOutputStream.java:134)
    at java.io.DataOutputStream.writeBytes(DataOutputStream.java:276)
    at Main.main(Main.java:24)

После этого клиентская сторона закрываетсяи серверная часть продолжает работать. HTTP и TCP реализованы из одного и того же класса Server, который запускает сервер.

MyServer:

public abstract class Server implements Runnable {

    private final Socket clientSocket;

    public Server(Socket clientSocket) {
        this.clientSocket = clientSocket;
    }

    @Override
    public void run() {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
             BufferedWriter output = new BufferedWriter(new PrintWriter(clientSocket.getOutputStream()))) {
            String req = getRequest(reader);
            setResponse(output, req);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

Класс, запускающий сервер:

public class RunServer extends Thread {
    private final int port;
    private ExecutorService executorService;
    private String serverType;
    private ServerFactoryContainer serverFactoryContainer;

    public RunServer(String serverType, int port) {
        this.port = port;
        this.executorService = Executors.newFixedThreadPool(4);
        this.serverType = serverType;
        this.serverFactoryContainer = new ServerFactoryContainer();
    }

    @Override
    public void run() {
            try {
                ServerSocket serverSocket = new ServerSocket(port);
                while (!isInterrupted()) {
                    Socket clientSocket;
                    try {
                        clientSocket = serverSocket.accept();
                        executorService.execute(serverFactoryContainer.getServerFactory(serverType).createServer(clientSocket));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

TCP-сторона клиента:

public class Main {
    public static void main(String[] args) throws IOException {
        String req;
        String resp;

        try (Socket clientSocket = new Socket(InetAddress.getLocalHost(), Constants.ServerConstant.TCP_PORT);
             BufferedReader inFromClient = new BufferedReader(new InputStreamReader(System.in));
             DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
             BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))) {
            while (true) {
                System.out.println("Write command [get count] or [get item]");
                req = inFromClient.readLine().toLowerCase();
                outToServer.writeBytes(req + "\n");  // I get an exception here when I send a request to the server

                resp = inFromServer.readLine();
                if (!resp.isEmpty()) {
                    System.out.println(resp);
                }
                if (req.equals("exit")) {
                    System.exit(1);
                }
            }
        }
    }

Почему я получаю исключение, которое я указал выше, при повторной отправке запроса на TCP-сервер, и почему это исключение не выдается при отправкевторой запрос к HTTP-серверу?

@Override
    protected String getRequest(BufferedReader input) throws IOException {
        return input.readLine();
    }

    @Override
    protected void setResponse(BufferedWriter output, String request) throws IOException {
        String result = serverCommandController.execute(RequestParser.tcpParserCommand(request));
        output.write(result);
        output.flush();
    }

Ответы [ 2 ]

0 голосов
/ 20 сентября 2018

Вы закрываете клиентское соединение до того, как клиент завершит работу.Попробуйте это в классе вашего сервера:

@Override
public void run()
{
  try (BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); BufferedWriter output = new BufferedWriter(new PrintWriter(clientSocket.getOutputStream())))
  {
    while (clientSocket.isConnected())
    {
      String req = getRequest(reader);
      setResponse(output, req);
    }
  }
  catch (IOException e)
  {
    e.printStackTrace();
  }
  finally
  {
    try
    {
      clientSocket.close();
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
  }
}
0 голосов
/ 20 сентября 2018

Ваш сервер закрывает сокет после отправки ответа.После этого клиент не сможет отправлять дальнейшие запросы без открытия нового соединения.Как правило, сервер позволяет клиенту контролировать судьбу соединения, чтобы клиент мог отправлять несколько запросов.Ваш клиент может отправить запрос «закрыть», чтобы указать серверу, что клиент намеревается закрыть сокет и не ожидает ответа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...