简体   繁体   中英

Socket in multithreading “deadlocked” Java

I am trying to launch server and client thread on the same process, but seems like the server thread is blocking the client thread (or vice versa). I'm not allowed to use any global variable between those threads(like semaphore or mutex, since the client and the server thread are launched by upper-class that I don't have the access of).

I found a similar question here , but it still use two different process (two main function).

Here is a sample of my code

The server code:

public class MyServer implements Runnable{

    ServerSocket server;
    Socket client;
    PrintWriter out;
    BufferedReader in;

    public MyServer() throws IOException{
        server = new ServerSocket(15243, 0, InetAddress.getByName("localhost"));
    }

    @Override
    public void run() {
        while(true){
            try {

                ArrayList<String> toSend = new ArrayList<String>();

                System.out.println("I'll wait for the client");
                client = server.accept();
                out = new PrintWriter(client.getOutputStream(), true);
                in = new BufferedReader(new InputStreamReader(client.getInputStream()));

                String inputLine;
                while((inputLine = in.readLine()) != null){
                    toSend.add("answering : "+inputLine);
                }

                for(String resp : toSend){
                    out.println(resp);
                }

                client.close();
                out.close();
                in.close();

            } catch (IOException ex) {
            }

        }
    }
}

And the client code:

public class MyClient implements Runnable{

    Socket socket;
    PrintWriter out;
    BufferedReader in;

    public MyClient(){
    }

    @Override
    public void run() {
        int nbrTry = 0;
        while(true){
            try {
                System.out.println("try number "+nbrTry);
                socket = new Socket(InetAddress.getByName("localhost"), 15243);

                out = new PrintWriter(socket.getOutputStream(), true);
                in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                out.println("Hello "+nbrTry+" !! ");

                String inputLine;
                while((inputLine = in.readLine()) != null){
                    System.out.println(inputLine);
                }
                nbrTry++;
            } catch (UnknownHostException ex) {
            } catch (IOException ex) {
            }
        }
    }
}

And the supposed upper-class launching those thread:

public class TestIt {

    public static void main(String[] argv) throws IOException{
        MyServer server = new MyServer();
        MyClient client = new MyClient();
        (new Thread(server)).start();
        (new Thread(client)).start();
    }
}

It gives me as output:

I'll wait for the client
Try number 0

And it stuck here. What should I do to keep both server and client code running? Thank you.

I'll be willing to take up your questions but basically you need to think through your logic a bit more carefully.

MyServer.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class MyServer implements Runnable {

  ServerSocket server;

  public MyServer() throws IOException {
    server = new ServerSocket(15243, 0, InetAddress.getByName("localhost"));
  }

  @Override
  public void run() {
    while (true) {
      try {
        // Get a client.
        Socket client = server.accept();

        // Write to client to tell him you are waiting.
        PrintWriter out = new PrintWriter(client.getOutputStream(), true);
        out.println("[Server] I'll wait for the client");
        // Let user know something is happening.
        System.out.println("[Server] I'll wait for the client");

        // Read from client.
        BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
        String inputLine = in.readLine();

        // Write answer back to client.
        out.println("[Server] Answering : " + inputLine);

        // Let user know what it sent to client.
        System.out.println("[Server] Answering : " + inputLine);

        in.close();
        out.close();
        client.close();
      } catch (Exception e) {

      }
    }
  }
}

MyClient.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

public class MyClient implements Runnable {

  Socket socket;
  PrintWriter out;
  BufferedReader in;

  public MyClient() throws UnknownHostException, IOException {
  }

  @Override
  public void run() {
    int nbrTry = 0;
    while (true) {
      try {
        // Get a socket
        socket = new Socket(InetAddress.getByName("localhost"), 15243);

        // Wait till you can read from socket.
        in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String inputLine = in.readLine();
        //inputLine contains the text '[Server] I'll wait for the client'. means that server is waiting for us and we should respond.

        // Write to socket
        out = new PrintWriter(socket.getOutputStream(), true);
        out.println("[Client] Hello " + nbrTry + " !! ");

        // Let user know you wrote to socket
        System.out.println("[Client] Hello " + nbrTry++ + " !! ");

      } catch (UnknownHostException ex) {
      } catch (IOException ex) {
      }
    }
  }
}

TestIt.java

import java.io.IOException;

public class TestIt {

  public static void main(String[] argv) throws IOException {
    MyServer server = new MyServer();
    MyClient client = new MyClient();
    (new Thread(server)).start();
    (new Thread(client)).start();
  }
}

Your client sends a string, then reads until the stream is exhausted:

                while((inputLine = in.readLine()) != null){

BufferedReader.readLine() only returns null at the end of the stream, as I recall. On a stream, it will block until input is available

Your server receives until the stream is exhausted, then sends back its response.

After sending one line, you now have:

  • Your client waiting for a response.
  • Your server still waiting for more data from the client. But it doesn't send anything back until the end of the stream from the client (which never happens because the client is waiting for your response).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM