2017-04-15 82 views
0

對不起,我看到的問題的漫長描述。Java多線程套接字 - 如何按順序發送響應

我有下面的代碼記錄,我一直在嘗試使它使用線程順序發送消息。我繼續在客戶端上獲取以下控制檯輸出。

呼應客戶端消息:您好:0 14210577 14210579

呼應客戶端消息:您好:1 14211379 14211379

呼應客戶端消息:您好:2 14212181 14212181

呼應客戶端消息:你好:3 14212981 14212982

呼應客戶留言:您好:4 14213782 14213782

呼應客戶端消息:您好:5 14214582 14214583

呼應客戶端消息:您好:6 14215383 14215383

呼應客戶端消息:您好:7 14216184 14216184

呼應客戶端消息:您好:8 14216984 14216984

呼應客戶端消息:您好:9 14217785 14217785

在CLIEN控制檯輸出我要找實現t是像下面

呼應客戶端消息(其中消息2之後的所有消息消息2之前發送):您好:0 14210577 14210579

呼應客戶端消息:您好: 1 14211379 14211379

呼應客戶端消息:您好:3 14212981 14212982

呼應客戶端消息:您好:4 14213782 14213782

ECH卷板機客戶端消息:您好:5 14214582 14214583

呼應客戶端消息:您好:6 14215383 14215383

呼應客戶端消息:您好:7 14216184 14216184

呼應客戶端消息:您好:8 14216984 14216984

呼應客戶端消息:您好:9 14217785 14217785

呼應客戶端消息:您好:2 14212181 14217885

客戶端上的控制檯輸出具有以下內容;並且我可以看到服務器對消息3的響應在消息2完成其等待時間之前不會被髮送。我希望服務器在消息2完成等待之前發送其對消息3的響應。

傳入客戶端消息:您好:2 15430652

調用ServerThread發送消息:15430653

從發送消息中返回ServerThread:15430653

在sendMessage.doWork()

:15430653

sendMessage.doWork()完成等待:15430753

傳入客戶端消息:您好:3 15430753

如何讓線程繼續處理其他消息而無需等待消息2完成等待?

在此先感謝您的任何意見。

服務器類:

// Built off the following tutorials 
// https://www.youtube.com/watch?v=2cQJJwoSNLk 
// https://www.youtube.com/watch?v=nCIw0h1C8Qo 

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.PrintWriter; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.util.concurrent.TimeUnit; 

public class Server{ 

    public static void main(String[] args) { 
     try { 
      new Server().runServer(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void runServer() throws IOException{ 
     final int PORT = 4444; 
     ServerSocket serverSocket = new ServerSocket(PORT); 
     System.out.println(new StringBuilder().append("Server up and ready for connections...").toString()); 
     while(true){ 
      Socket socket = serverSocket.accept(); 
      new Thread(new ServerThread(socket)).start(); 
     } 
    } 

    public class ServerThread implements Runnable{ 

     private Socket socket; 
     private String message; 

     ServerThread(Socket socket){ 
      this.socket = socket; 
     } 

     public void run(){ 

      try { 
       this.message = null; 
       PrintWriter printWriter = new PrintWriter(socket.getOutputStream(),true); 
       BufferedReader bufferedReader = new BufferedReader(new InputStreamReader (socket.getInputStream())); 
       while((message = bufferedReader.readLine()) != null){ 
        System.out.println(new StringBuilder().append("incoming client message: ").append(message).toString()); 
        long sendTime = System.nanoTime(); 
        if(message.trim().startsWith("Hello: 2")){ 
         sendTime = System.nanoTime() + 100000000; 
        } 

        System.out.println(new StringBuilder().append("calling Send Message in ServerThread: ").append(" ").append(TimeUnit.NANOSECONDS.toMillis(System.nanoTime())).toString()); 

        new Thread( 
          new SendMessage(printWriter, 
              sendTime, 
              new StringBuilder().append("echoing client message: ").append(message).append(" ").append(TimeUnit.NANOSECONDS.toMillis(System.nanoTime())).toString() 
              ) 
          ).start(); 

        System.out.println(new StringBuilder().append("returned from Send Message in ServerThread: ").append(" ").append(TimeUnit.NANOSECONDS.toMillis(System.nanoTime())).toString()); 
       } 
      } catch (IOException e) { 
      } 

     } 

    } 

} 

客戶端類:

// Built off the following tutorials 

// https://www.youtube.com/watch?v=2cQJJwoSNLk 

// https://www.youtube.com/watch?v=nCIw0h1C8Qo 



import java.io.BufferedReader; 

import java.io.IOException; 

import java.io.InputStreamReader; 

import java.io.PrintWriter; 

import java.net.Socket; 

import java.net.UnknownHostException; 

import java.util.concurrent.TimeUnit; 


public class Client { 

public static final int PORT = 4444; 

public static void main(String[] args) throws UnknownHostException, IOException { 

    Socket socket = new Socket("localhost",PORT); 
    PrintWriter printWriter = new PrintWriter(socket.getOutputStream(),true); 
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
    for(int x = 0; x<10;x++){ 
     if(x==5){ 
      printWriter.println(new StringBuilder().append("Hello: ").append(x).append(" ").append(TimeUnit.NANOSECONDS.toMillis(System.nanoTime())).toString()); 
     }else{ 
      printWriter.println(new StringBuilder().append("Hello: ").append(x).append(" ").append(TimeUnit.NANOSECONDS.toMillis(System.nanoTime())).toString()); 
     } 
     System.out.println(new StringBuilder().append(bufferedReader.readLine())); 
    } 
    //socket.close(); 
} 


} 

SendMessage函數類:

import java.io.PrintWriter; 
import java.util.concurrent.TimeUnit; 

public class SendMessage implements Runnable{ 

private PrintWriter printWriter; 
private Long SendTimeInNanos; 
private String message; 

public SendMessage(PrintWriter printWriter, Long SendTimeInNanos, String message){ 
    this.printWriter = printWriter; 
    this.SendTimeInNanos = SendTimeInNanos; 
    this.message = message; 
} 

@Override 
public void run() { 
    doWork(); 
} 

private void doWork(){ 
    System.out.println(new StringBuilder().append("in sendMessage.doWork(): ").append(" ").append(TimeUnit.NANOSECONDS.toMillis(System.nanoTime())).toString()); 
    //sleep until the appropriate time 
    while(this.SendTimeInNanos > System.nanoTime()){ 
     try { 
      //sleep until appropriate time 
      Thread.sleep(TimeUnit.NANOSECONDS.toMillis(this.SendTimeInNanos-System.nanoTime())); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 

    System.out.println(new StringBuilder().append("sendMessage.doWork() done waiting: ").append(" ").append(TimeUnit.NANOSECONDS.toMillis(System.nanoTime())).toString()); 

    //send at appropriate time 
    this.printWriter.println(new StringBuilder().append(this.message).toString()); 
} 

} 
+0

如果您想要特定的序列,爲什麼要使用線程? – EJP

+0

我不想要一個特定的序列,但我想模擬丟棄和延遲的數據包......丟棄的數據包很容易模擬......只是不發送它們......延遲的數據包似乎是一個問題模擬。 – merkman

回答

0

總體代碼看起來確定。這個問題可能是你創建的方式,開始你的主題:

while(true){ 
     Socket socket = serverSocket.accept(); 
     new Thread(new ServerThread(socket)).start(); 
    } 

看起來像每一個新的線程創建一個新的前相當快完成其執行。要實現異步線程執行,請嘗試創建若干個ServerThread實例並一次啓動所有實例:

while(true){ 
     Socket socket = serverSocket.accept(); 
     List<Thread> threads = new ArrayList<>(); 
     for (int i = 0; i < 4; i++) 
     { 
      threads.add(new Thread(new ServerThread(socket))); 
     } 
     threads.forEach(Thread::start); 
} 
+0

所以....你是說每個客戶端消息應該有自己的服務器線程? – merkman