简体   繁体   English

多线程“死锁” Java中的套接字

[英]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 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 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 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. 我记得,BufferedReader.readLine()仅在流的末尾返回null。 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). 但是它不会将任何内容发送回客户端,直到客户端流结束为止(这永远不会发生,因为客户端正在等待您的响应)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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