2011-04-18 6 views
0


Java NIO를 사용하여 간단한 인스턴트 메신저를 작성하고 있습니다. 해당 클라이언트가 이미 기록 된 연락처와 메시지를 얻을하지 않습니다 exept 그것은 잘 작동하고
이 주 서버의 처리 방법이다.Java NIO - SocketChannels를 사용하여 데이터를 수신 할 때의 문제점

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

게시 한 코드로 대답하는 것은 불가능합니다. 문제를 설명하는 작은 코드 샘플을 작성해야합니다. 그렇게 할 때 문제가 발생할 수도 있습니다. –

답변

1

내 생각 엔 클라이언트에서 ...

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

가 전체 메시지를 읽을 보장되지 않는 것입니다 이해할 수있을 것이다, 그것은 그것 또는 여러 개의 메시지 중 일부를 아무 것도 읽을 수 있습니다.

소켓은 바이트 스트림이며 패킷을 읽으려는 경우 스트림을 패킷 화해야합니다.

이렇게하는 한 가지 방법은 패킷의 길이를 앞에두고 처리를 시도하기 전에 전체 패킷을 읽어야합니다.

또 다른 방법은 터미네이터를 얻을 때까지 읽은 고유 한 터미네이터가있는 방식으로 패킷을 쓰는 것입니다.

+0

수정. 그는 증거없이 전체 메시지를 읽었다 고 가정합니다. – EJP

관련 문제