Locked socket when performing data exchange

Asked

Viewed 1,367 times

0

I am trying to carry out server and client code in Java for the client to send a String, the server process and return it and the client receive.

The customer is kept always listening.

But after receiving the String he hangs.

Server class

// porta do servidor
    int serverDoor = 4000;

    // numero maximo de conexões que o servidor aceita
    int maxConnections = 10;

    // servidor socket
    ServerSocket server = null;

    // conexão socket
    Socket connection = null;

    // saida dos dados
    OutputStream output = null;

    // entrada dos dados
    InputStream input = null;

    try {

            server = new ServerSocket(serverDoor, maxConnections);

            while (true) {

            System.out.println("Esperando cliente");

            connection = server.accept();

            // abrindo o stream de saida
            output = connection.getOutputStream();
            output.flush();

            // abrindo o stream de entrada
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));

            // recebendo
            String teste = bufferedReader.readLine();

            output.write("Teste".getBytes());
            output.flush();

        }

    } catch (IOException e) {

        e.printStackTrace();

    } finally {

        try {

            if (output != null) {
                output.close();
            }

            if (input != null) {
                input.close();
            }

            if (connection != null) {
                connection.close();
            }

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

    }           
}

Customer class

Socket client;
OutputStream output;
InputStream input;

// Step 1: Create a Socket to make connection
client = new Socket(InetAddress.getByName(url), porta);
//client.setSoTimeout(15000); // 5 segundos

// Step 2: Get the input and output streams
output = client.getOutputStream();
output.flush();
input = client.getInputStream();

// Step 3: Process connection
output.write(msg.getBytes());
output.flush();

// recebendo
System.out.println("Antes de receber cliente");
StringBuilder sb = new StringBuilder();
int temp;
while ((temp = input.read()) > -1)
    sb.append((char) temp);
System.out.println("Depois de receber cliente");

// Step 4: Close connection
if (output != null)
    output.close();
if (input != null)
    input.close();
if (client != null)
    client.close();

return sb.toString();

}

After the method of receiving the String it to, I use Windows 8, I don’t know if this can represent something.

  • 1

    Why new ServerSocket(serverDoor, maxConnections) is inside an infinite loop?

  • @pepper_chico arranged but still gives the problem.

  • Where is msg, the message you send? As I do not see, I do not know if there is an end-of-line in it, since the server makes a readLine() and will wait for the end-of-line to arrive.

  • @pepper_chico it comes as parameter, is a static class method the client.

  • The point is, she has an end-of-line?

  • write the client will send data without adding extra end-of-line, and the server does readLine().

  • @pepper_chico sorry, but I didn’t quite understand what you meant, could you reply with the edited code please? I changed the method to readline because I found it on the net and it seemed to be simpler than the client’s tie.

  • 1

    understand end-of-line as '\n'. Your server says that you understand an end of a message with this character, because you use a readLine. But in the customer you send data via write which will only write the characters you request, and if there is no '\n' your server will be waiting for one. If there is a method writeLine, this will add a '\n' for you.

  • @pepper_chico understood, talking to different objects if I can say so.

  • 1

    see the tips and comments in the other answers also.

Show 5 more comments

2 answers

2


You need to close the output on the server so the client understands that the message is over:

// recebendo
String teste = bufferedReader.readLine();

output.write("Teste".getBytes());
output.flush();
output.close();

And the server can also crash if the client does not return an n at the end of the message according to the documentation of the Bufferedreader#readline()

// Step 3: Process connection
output.write(msg.getBytes());
output.write('\n');
output.flush();

A suggestion to improve your code would be to use PrintWriter and BufferedReader client and server. You are using different ways of reading and writing.

Here’s a detailed example.

  • 2

    There is no need to "close output", just send "end-of-line". TCP is intended to be useful for permanent connections, so you don’t have to keep opening and closing connections when you don’t need to.

  • In this case it is necessary to close the output, because the client’s part is not expecting an "end-of-line". However, as I said earlier, the server part expects the "end-of-line".

  • 2

    You’re saying it’s necessary give away close previously on output in the client part (note that it does this at the end), so that then it is possible to have the sending of data? I don’t know how this Java part works, I don’t program Java but I know TCP from other languages and it doesn’t make much sense to me.

  • I’m saying it’s necessary give away close in the output in part server (something it does not do on the server, because the server is in infinite loop listening by clients), so it is possible that the client stop trying to receive.

  • Not exactly this, it’s not necessary to give close, most proper is to say that necessary to restructure the communication, it is in loop making accept. A connection obtained through accept previously could give continuity of communication in parallel while it continues accepting more customers. But in fact, the lack of close anywhere on the server indicates a problem but would not completely prevent you from receiving communication.

  • I totally agree, but since his solution does not require continuity of communication, I preferred not to go into more detail! Abs!

  • @vrcca could you tell me why this your improvement suggestion please?

  • To have uniformity (in addition to ease of maintenance and reading) in the implementation of communication between client and server. For example, in the client you are dealing directly with bytes, while it would be much simpler to deal with Strings through the Bufferedreader and Printwriter classes (in addition to having better treatment with multiple threads, etc).

Show 3 more comments

2

In the server class the closure of the output stream (output) is in an improper location, Finally. This Finally will only be executed when the scope of Try comes to an end, that is, when the looping ends, but it is infinite, and "never" will be closed and for this reason the client "hangs".

The client is "locked", or better, waiting for more bytes in this stretch:

...
// recebendo
System.out.println("Antes de receber cliente");
StringBuilder sb = new StringBuilder();
int temp;
while ((temp = input.read()) > -1)
        sb.append((char) temp);
System.out.println("Depois de receber cliente");
...

The only condition of termination of the while is read() return -1 (or less), which will normally only occur when there is an end to the data stream via close() on the server (and network problems, etc.). Thus, the input.read() method call freezes, because the server output is still open and as a consequence the client input is waiting for more data and has the impression that "locked";

Finally, the purpose of looping in this question is to treat a connection for each client, as a consequence input and output are instantiated to each Accept() of the Serversocket instance and therefore must be closed at each iteration. To this end, you can close the Connection, as it will be in charge of closing everything that is pending.

Following this reasoning the source code for the server would look like this:

// porta do servidor
int serverDoor = 4000;

// numero maximo de conexões que o servidor aceita
int maxConnections = 10;

// servidor socket
ServerSocket server = null;

try {

    server = new ServerSocket(serverDoor, maxConnections);

    while (true) {

        System.out.println("Esperando cliente");

        // conexão socket, dentro do looping
        Socket connection = null;

        // saida dos dados, dentro do looping
        OutputStream output = null;

        // aceitando a conexão
        connection = server.accept();

        // abrindo o stream de saida
        output = connection.getOutputStream();
        output.flush();

        // abrindo o stream de entrada
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));

        // recebendo
        String teste = bufferedReader.readLine();

        output.write("Teste".getBytes());
        output.flush();

        // fechando tudo!
        connection.close();
    }

} catch (IOException e) {

    e.printStackTrace();

}
  • 1

    +1, tip: add note that... the customer is expecting an end stream when checking by -1, therefore and because of this way of working, the server needs to finish the stream via close, which does not imply that every TCP server needs to give close for each message sent, just the customer understand end-of-message that is not end-of-stream.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.