2016-11-13 45 views
0

我正在构建连接到服务器并发送消息的客户端。我有这个部分,服务器正在收到消息,但我的问题是让我的客户端监听来自服务器的消息。本质上,它就像一个聊天室,我必须将消息发送到服务器,而我的客户端也需要从服务器接收消息,并在服务器发送消息时将其打印出来。使用线程和套接字获取服务器响应

我没有构建服务器,也没有访问服务器代码,但我确实知道服务器的工作原理。下面是我的客户端,SendThread工作得很好,但是当我添加一个GetThread时,发送线程不再工作,所以我不能得到2个线程工作,一个监听和一个发送。

Client.java

public class Client { 
    public static void main(String[] args) throws IOException { 

     // String name = args[0]; 
     String name = "Brandon"; 
     Socket socket = new Socket("localhost", 4688); 
     Thread sendThread = new SendThread(socket, name); 
     Thread getThread = new GetThread(socket); 
     sendThread.start(); 
     getThread.start(); 
    } 
} 

SendThread.java

public class SendThread extends Thread { 
    Socket socket; 
    String name; 
    SendThread(Socket s, String n) { 
     socket = s; 
     this.name = n; 
    } 

    public void run(){ 
     try{ 
      String message; 
      PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true); 
      printWriter.println("connect Brandon"); 
      BufferedReader bufferedReaderFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
      System.out.println(bufferedReaderFromClient.readLine()); 
      BufferedReader bufferedReader = new java.io.BufferedReader(new InputStreamReader(System.in)); 
      while(true) { 
       String readerInput = bufferedReader.readLine(); 
       printWriter.println(name + ": " + readerInput); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

GetThread.java

public class GetThread extends Thread { 
    Socket socket; 

    GetThread(Socket s) { 
     socket = s; 
    } 

    public void run(){ 
     try{ 
      String message; 
      BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
      while((message = bufferedReader.readLine()) != null) { 
       System.out.println("Incoming: " + message); 
      } 
      socket.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

} 
+0

它看起来像两个线程工作..我只是无法得到积极 –

+0

两个线程都在哪里或不每个线程成为卡住时? – acelent

+0

阅读关于套接字和线程http://www.oracle.com/technetwork/java/socket-140484.html#multi –

回答

1

不要CR吃了第二个BufferedReader。在插座的使用寿命中使用相同的一个。您正在丢失第一位读者已经缓冲的数据。

如果readLine()返回null,则需要跳出读取循环。

+0

感谢您的回复....我将如何去使用相同的BufferedReader?如果我在客户端实例化它,我无法在线程 –

+0

叹息中访问它。你正在同一个'run()'方法中实例化两个'BufferedReaders'。你不应该需要向你解释你自己的代码。你也在发送线程中进行输入,如果你还*有一个单独的接收线程,这是没有意义的。你需要退后一步,思考你在这里试图完成什么。 – EJP

-1

看起来像一个竞赛条件。 readLine()会阻塞,直到发送消息,并且发生这种情况时,GetThread或SendThread都会抓住它,让另一个等待一次。如果您需要在两个线程的消息,以避免并发问题,你应该考虑显示器:

public class Monitor { 
    private String msg; 
    private boolean hasMsg = false; 

    public synchronized void newMsg(String msg) { 
     this.msg = msg; 
     hasMsg = true; 
     notifyAll(); 
    } 

    public synchronized String getMsg() { 
     try { 
      while (!hasMsg) wait(); 
     } catch (InterruptedException e) {}; 

     hasMsg = false; 
     return msg; 
    } 
} 

public class Client { 
    // ... 
    Monitor m = new Monitor(); 
    Thread sendThread = new SendThread(m, socket, name); 
    Thread getThread = new GetThread(m, socket); 
    // ... 
} 

public class GetThread extends Thread { 
    private Monitor monitor; 
    private Socket socket; 
    public GetThread(Monitor m, Socket s) { 
     monitor = m; 
     socket = s; 
    } 

    public void run() { 
     // ... 
     while((message = bufferedReader.readLine()) != null) { 
      monitor.newMsg(message); 
      System.out.println("Incoming: "+message); 
     } 
     // ... 
    } 
} 

public class SendThread extends Thread { 
    private Socket socket; 
    private Monitor monitor; 
    private String name; 
    public SendThread(Monitor m, Socket s, String n) { 
     monitor = m; 
     socket = s; 
     name = n; 
    } 

    public void run() { 
     // ... 
     String readerInput = monitor.getMsg(); 
     printWriter.println(name + ": "+readerInput); 
     // ... 
    } 
} 
+0

我在自己的类中添加了监视器....在每个类的顶部调用监视器(发送和获取线程),它只从服务器侦听....我不能让它发送到服务器总之......不知道我在这里做错了什么! –

+0

SendThread和GetThread都需要Monitor对象的同一个实例。通常,您首先创建Monitor对象,然后将其传递给需要它的线程。 – Lidae

相关问题