2015-04-02 69 views
-2

好的,所以我一直在收到一些讓我的代碼工作的問題,所以我做了一個簡化版本的程序來弄清楚發生了什麼,但我仍然感到困惑。多線程程序中意外的I/O中斷

這裏的程序:

這是服務器代碼:

public class Server{ 

    private ServerSocket server; 
    private Socket connection; 
    private DatagramSocket server_socket; 
    String compString = ""; 
    public static List<String> messages = Collections.synchronizedList(new ArrayList<String>()); 
    public static List<DatagramPacket> packets = Collections.synchronizedList(new ArrayList<DatagramPacket>()); 


    public Server() 
    {    
    } 

    public void startRunning() 
    { 
      try 
      { 
       server_socket = new DatagramSocket(9876);  
       receiveAndSend();    
      }catch(Exception e) 
      { 
       System.out.println("Exception caught"); 
      } 
    } 

    public void receiveAndSend() 
    { 
     Thread thread1 = new Thread() 
     { 
      public void run() 
      { 
       try{ 
       while(true) 
       { 
        byte[] buffer = new byte[3000]; 
        DatagramPacket request = new DatagramPacket(buffer, buffer.length); 
        server_socket.receive(request); 
        String mess = new String(request.getData());       
        synchronized(messages) 
        { 
         if(!messages.contains(mess) && !packets.contains(request)) 
         {        
          addMessage(mess); 
          addPacket(request);        
          System.out.println("added: " + mess);    
         }    
        }      
       } 
       }catch(Exception e) 
       { 
        System.out.println("Exception caught"); 
       }   
      }    
     }; 
     thread1.start();    
     Thread thread2 = new Thread() 
     {  
      public void run() 
      { 
       try 
       { 
        while(true) 
        { 
         Thread.sleep(6000);   
         System.out.println("the list contains");        
         synchronized(messages) 
         { 
          compString = "";      
          for (String st : messages) 
          {  
           System.out.println(st); 
          } 
          System.out.println("!!!!!!!!!!!!!!!!!!");  

          if(!messages.isEmpty()) 
          { 

           System.out.println(messages.size());          

           for(int i=0; i< messages.size(); i++) 
           {     
            compString += messages.get(i); 
            compString += "-"; 

           }               
          }        
         }        
         System.out.println("final string is:" + compString + "\n");      
         for(DatagramPacket pack: packets) 
         { 
          try 
          {     
           InetAddress add = pack.getAddress(); 
           int port = pack.getPort(); 

           byte[] tbuffer = compString.getBytes(); 
           DatagramPacket reply = new DatagramPacket(tbuffer, tbuffer.length, add, port); 
           server_socket.send(reply); 
          }catch(Exception e) 
          { 
           System.out.println("Exception caught"); 
          } 

         }  
        }     

       }catch(Exception e) 
       { 

       }   
      }    
     };    
     thread2.start();  
    } 

    public synchronized void addMessage(String mess) 
    {  
     messages.add(mess); 
    } 
    public synchronized void addPacket(DatagramPacket packet) 
    { 
     packets.add(packet); 
    }  
} 

這是客戶端代碼:

public class Client { 

public String message; 
public int port; 
public int server = 9876; 

public void Client(String message) 
{ 
    this.message = message; 
} 

public void startRunning() 
{ 
     serverStart(); 
} 


public void serverStart() 
{ 
    Thread thread1 = new Thread() 
    {  
     public void run() 
     { 
      try{       
       DatagramSocket ssocket = new DatagramSocket(port);    
      while(true) 
      {     
        Thread.sleep(5000); 
        byte [] m =message.getBytes(); 
        InetAddress hhost = InetAddress.getByName("127.0.0.1"); //won't be always localh 

        DatagramPacket request = new DatagramPacket(m, m.length, hhost, server);       
        ssocket.send(request); 

        System.out.println("sending: " + message + "\n"); 

        byte[] buffer = new byte[2000]; 
        DatagramPacket reply = new DatagramPacket(buffer, buffer.length);      
        ssocket.receive(reply); 

        String receivedString = new String(reply.getData()); 

        System.out.println("receivedString : " + receivedString); 
        if(receivedString != null && !receivedString.isEmpty()) 
        { 


        }     

      } 
      }catch(Exception e) 
      { 
       System.out.println("Exception caught"); 
      } 


     } 
    }; 

    thread1.start();   

} 

public String[] convertStringToArray(String tstring) 
{ 
    tstring.trim(); 

    String[] sarray = tstring.split("-"); 

    return sarray; 
} 

}

您需要這3個運行代碼:

public class ServerTest { 

    public static void main(String[] args) 
    { 
     Server s = new Server(); 
     s.startRunning(); 
    } 

} 

public class ClientTest2 { 

    public static void main(String[] args) 
    { 
     Client myclient = new Client(); 
     myclient.message = "Hello"; 
     myclient.port = 6965; 
     myclient.startRunning();    

    } 

} 

public class ClientTest { 

    public static void main(String[] args) 
    { 
     Client myclient = new Client(); 
     myclient.message = "Kitty"; 
     myclient.port = 6646; 
     myclient.startRunning(); 

    }   

} 

我得到下面的輸出,當我運行:

added: Helloadded: Kittythe list contains 
Hello2 
final string is:Hellothe list contains 
Hello 
!!!!!!!!!!!!!!!!!! 
2 
final string is:Hello 
the list contains 
Hello 
!!!!!!!!!!!!!!!!!! 

的問題是:1)中的println有時會被中斷,從不在上面的輸出中,我們可以看到該行!!!! !!!!!!!!!!有時候不會打印出來。 2)Arraylist中的某些元素不會被添加或不會被打印。

我確實試圖在每個地方放置同步的塊,但它似乎並沒有工作,其他各種事情也沒有幫助。

+4

(脫離主題,但與獲得更好的幫助有關):一個空行足夠空白 - 爲了獲得更好的幫助,請將代碼格式化得很好,以便我們可以讀取它。 – 2015-04-02 04:10:02

+0

'catch(Exception e) { }'是問題所在。想想看... – Holger 2015-04-02 16:46:20

+0

不,不是。我刪除了catch塊內的打印語句,因爲我想查看這種行爲是否會以某種方式改變。前一段時間我添加了這些語句,輸出完全沒有改變。 – jarvan 2015-04-02 18:38:27

回答

0

你沒有正確序列化/反序列化你的字符串。

在你的服務器,你應該指定從接收緩衝器取數據的字節範圍,以及客戶端使用的編碼:

String receivedString = new String(reply.getData(), 0, reply.getLength(), "UTF-8"); 

在你的客戶,你應該指定編碼使用連載字符串:

byte[] m = message.getBytes("UTF-8"); 

此外,DatagramPacket.equals()只做參考比較(即它只有當傳遞到自身的引用返回true;它不是在與自己的其他分組比較數據),所以!packets.contains(request)永遠是真實的。

+0

但似乎arraylist只包含1個元素,是線程被中斷或什麼,或者它只是I/O,因爲我沒有得到任何異常? – jarvan 2015-04-02 16:19:42