1
votes

I've got a Client and a Server. The client simply sends 1 line of input to the server and then prints the response.

I'm getting a

SocketException (Software caused connection abort: recv failed) 
    [...]
    at java.io.InputStreamReader.read(InputStreamReader.java:168)
    at hw3.Client.readLine(Client.java:37)
    at hw3.Client.main(Client.java:28)

The debugger tells me that the socket is not closed at the time of the read, what else can cause this exception?

I think I'm running into issues because of the threading, does anything stick out as "doing it wrong"?

public class Client
{
    public static final int PORT = ReversingEchoServerDispatcher.PORT;
    private static final String host = "localhost";
    private static Socket sock;

    public static void main(String[] args)
      throws IOException
    {
        try(Socket sock = new Socket(host, PORT);
            InputStreamReader clin = new InputStreamReader(sock.getInputStream());
            OutputStream clout = sock.getOutputStream();
            Scanner sc = new Scanner(System.in))
        {
            Client.sock = sock;

            byte[] cl = sc.nextLine().getBytes("UTF-8");
            clout.write(cl);
            System.out.println(readLine(clin));
        }
    }

    private static String readLine(InputStreamReader in)
      throws IOException
    {
        StringBuilder sb = new StringBuilder();
        for(int i = in.read(); i != -1; i = in.read())
        {
            char c = (char) i;
            if(c != '\n') sb.append(c);
            else break;
        }
        return sb.toString();
    }
}

public class ServerDispatcher
{
    public static final int PORT = 8034;
    public static void main(String[] args)
    {
        try (ServerSocket serversock = new ServerSocket(PORT))
        {
            while(true)
            {
                Socket socket = serversock.accept();
                ServerLogic sv = new ServerLogic(socket);
                new Thread(() -> {
                    try {
                        sv.run();
                    } catch (IOException ex) {
                        ex.printStackTrace(System.err);
                    }
                }).start();
            }
        }
        catch(IOException e)
        {
            e.printStackTrace(System.err);
        }
    }
}

For the record, the ServerLogic class looks something like the following. My exit code is 1, not -999, so it's not that socket.close() is failing

class ServerLogic
{
    Socket socket;

    public
    ServerLogic(Socket s)
    {
        this.socket = s;
    }

    public void run()
      throws IOException
    {
        try(InputStreamReader in = new InputStreamReader(socket.getInputStream());
            OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream()))
        {
            StringBuilder sb = new StringBuilder();
            while(in.ready()) {
                char c = (char) in.read();
                if(c == '\n') {
                    String str = process(sb);
                    if(str != null) out.write(str);
                    else return;
                } else {
                    sb.append(in.read());
                }
            }
        } finally {
            try {
                socket.close();
            } catch(IOException ex) {
                ex.printStackTrace(System.err);
                System.exit(-999);
            }
        }
    }

    private static String process(StringBuilder sb)
    { /* ... */ }
1
try calling flush() on clout on the client side after the write.MeBigFatGuy
Nope, that didn't fix it.Matt G
i wouldn't use in.ready() either. there's no point. What if it returns null immediately? nothing happens... get rid of that... just readMeBigFatGuy

1 Answers

0
votes

The server is expecting a newline \n to terminate the input but you never send one from the client. sc.nextLine() returns the input line but does not include the terminating newline. The while(in.ready()) loop eventually ends and the server closes the socket without ever sending a response.