2011-04-18 48 views
0


我正在使用Java NIO編寫簡單的即時通訊程序。它的正常工作exept客戶端不與已經被記錄在通訊錄中獲取消息
這是主要的服務器進程方法:Java NIO - 使用SocketChannel接收數據的問題

public void process() throws IOException, ClassNotFoundException{ 
    while (true){ 
     selector.select(); 
     Set keys = selector.selectedKeys(); 
     Iterator it = keys.iterator(); 
     while (it.hasNext()){ 
      SelectionKey key = (SelectionKey)it.next(); 
      it.remove(); 
      if (key.isAcceptable()){ 
       /*configuring incoming channel to be non-blocking 
       and adding it to the clients set*/ 
      } 
      if (key.isReadable()) { 
       SocketChannel client = (SocketChannel)key.channel(); 
       /*Message class contains its type, source user name and data. 
       getMessage() method reads message from SocketChannel*/ 
       Message m = getMessage(client);  
       switch (m.getType()) { 
        case LOGIN_REQUESTED: 
         /*Accept or reject the client log in name 
         in case of accepting add user with its status 
         to Map users*/ 
         break; 
        case CONTACTS_REQUESTED: 
         /*Here is the problem, client gets only one message 
         sendMessage() writes the buffer with serialized 
         message to clients channels*/ 
         for (String name : users.keySet()) { 
          sendMessage(client, MessageType.CONTACTS_REQUESTED, 
           name, users.get(name).toString()); 
         } 
         break; 
        //Other messages are processing 
       } 
      } 
     } 
    } 
} 

客戶端的方法,它處理收到的消息:

private void processIncomingMessages() 
    throws IOException, ClassNotFoundException { 
    ByteArrayInputStream bais; 
    ObjectInputStream ois; 
    ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE); 
    while (true){ 
     selector.select(); 
     Set keys = selector.selectedKeys(); 
     Iterator it = keys.iterator(); 
     while (it.hasNext()){ 
      SelectionKey key = (SelectionKey)it.next(); 
      it.remove(); 
      if (key.isReadable()){ 
       SocketChannel sc = (SocketChannel)key.channel(); 
       buffer.clear(); 
       if (sc.read(buffer) != -1){ 
        buffer.flip(); 
        bais = new ByteArrayInputStream(buffer.array()); 
        ois = new ObjectInputStream(bais); 
        Message m = (Message)ois.readObject(); 
        /*My castom event serves to notify GUI to update 
        its contact list. In case of sending CONTACTS_REQUESTED 
        messages, it gets only one (first?) of them*/ 
        fireNetworkEvent(m); 
       } 
      } 
     } 
    } 
} 

其他消息分開發送給客戶端,沒有任何問題。 如果有任何問題,請詢問。任何幫助將不勝感激

+0

無法用您發佈的代碼來回答。你應該把它歸結爲一個能夠證明問題的小代碼示例。你甚至可能會發現這樣做的問題。 – 2011-04-18 23:38:56

回答

1

我的猜測是,在客戶端...

if (sc.read(buffer) != -1){ 

不能保證讀你的整個消息,它可以讀取什麼,它的一些或多個消息。

套接字是字節流,如果你想讀取一個數據包(和你一樣),你需要打包數據流。

要做到這一點的一種方法是預先確定數據包的長度,並確保在嘗試處理之前閱讀整個數據包。

另一種方式是編寫數據包,使其具有獨特的終止符,直到獲得終止符。

+0

正確。他假設他已經閱讀了全部信息,沒有證據。 – EJP 2011-04-19 00:57:07