2016-09-12 4 views
0

을 사용하여 3 개의 패킷 중 2 개만 보내고 있습니다. 따라서 AsynchronousSocketChannel 클래스를 기반으로 한 서버 통신 응용 프로그램 <을 빌드하고 있습니다. 나는 모든 것을 작동시킬 수 있었다 : 서버가 돌아 갔고, 클라이언트가 연결할 수 있고, 패킷이 모두 보내고 받고있다. 적어도 한 묶음의 패킷을 하나씩 보내려고 할 때까지 (처음에는 3 패킷을 말합니다), 처음에는 조금 검색 한 후에 수정할 수있는 WritePendingException을 실행했지만 패킷은 아직 보내지 않고 있습니다. 정확히. 내 디버그에서 서버가 3 패킷을 보내려고했지만, 성공적으로 모두 3을 보냈지 만 클라이언트는 처음 2 개만 수신합니다. 문제가 어디 있는지 이해할 수없고 콘솔에 오류가 전혀없는 것 같습니다.비동기 소켓

패킷을 생성, 그들과 같이 _sendQueue에 추가되고 있습니다 :

_sendQueue.add(packet); 

_sendQueue는 ByteBuffer의의 ConcurrentLinkedQueue를 (내 패킷되는) 나를 그냥 물어 도움이 필요합니다. 은 다음 패킷은 다음과 같은 방법으로 전송되는 :

public final void executeWriteTask() 
{ 
    if (!_sendQueue.isEmpty()) 
    { 
     _writeLock.lock(); 
     if (!_pendingWrite) 
     { 
      _pendingWrite = true; 

      ThreadPool.execute(() -> 
      { 
       final PacketWriter packet = _sendQueue.poll(); 
       final ByteBuffer duplicate = packet.getBuffer().duplicate(); 
       System.out.println("Sending packet opcode: " + duplicate.getInt()); 
       _channel.write(packet.getBuffer(), this, _writeHandler); 
      }); 
     } 
     _writeLock.unlock(); 
    } 
} 

모든 패킷이 기록 된 후, 방법은 큐에서 다음 패킷 다시 호출되고 그래서 기본적으로 전송되는 모든 3이 무엇 내에 println입니다 표시 : 다시 수동으로 된 후 3 초를 읽고 전화를 시도처럼, 많은 것들을 시도

Received packet opcode: 0 
Received packet opcode: 1 
하지만 : 괜찮지 만, 클라이언트

Sending packet opcode: 0 
Sending packet opcode: 1 
Sending packet opcode: 1 

수신 대기중인 패킷이 없었고, 3 초 후에 서버에서 3 번째 패킷을 보내려고했지만 작동하지 않았습니다.하지만 원하는 것은 아닙니다. 실제로 문제가 실제로 시도했는지 확인하는 것이 었습니다. 즉시 3 개의 패킷을 보내면 알았습니다. 그래서 세 번째 패킷은 어디로 갔습니까? 더 이상 디버깅 할 방법을 생각할 수 없습니다 ... 어떤 도움을 주시면 감사하겠습니다.

참고 독자적으로 작성하고 싶습니다. 따라서 미리 만들어진 통신 코드를 제안하지 마십시오.

+0

패킷이 네트워크에서 항상 손실됩니다. 일반적으로 매우 작은 버퍼가 채워질 수 있으므로 패킷이 삭제됩니다. 이것이 TCP가 안정적인 통신을 제공하기 위해 만들어진 이유입니다. –

+0

미안하지만, 나는 자바의 AsynchronousSocketChannel –

+0

TCP를 기반으로 한 TCP가 세그먼트 전달을 보장하고, 누락 된 세그먼트를 재전송하도록 요청했기 때문에 내 통신이 TCP를 기반으로한다는 것을 확신합니다. TCP로 모든 것을 얻을 수 있습니다. –

답변

0

음, 아직 내 질문에 직접 대답하지 않지만 문제를 해결하는 것 같습니다. 내가 거기에 생각이 패킷 홍수 정도 방지 할 몇 가지 메커니즘, 그래서 내가 대신 패킷을 차례로 전송, 그들은 1 개 패킷에 일괄 처리되고 있으며, 다음과 같이, 전체 전송되는 결정 :

public final void executeWriteTask() 
{ 
    if (!_sendQueue.isEmpty()) 
    { 
     _writeLock.lock(); 
     if (!_pendingWrite) 
     { 
      _pendingWrite = true; 

      ThreadPool.execute(() -> 
      { 
       final Queue<PacketWriter> copy = new ConcurrentLinkedQueue<>(); 
       while (!_sendQueue.isEmpty()) 
        copy.add(_sendQueue.poll()); 

       int bytes = 0; 
       for (final PacketWriter packet : copy) 
        bytes += packet.getBuffer().limit(); 
       final ByteBuffer toSend = ByteBuffer.allocateDirect(bytes); 
       for (final PacketWriter packet : copy) 
        toSend.put(packet.getBuffer()); 
       toSend.flip(); 

       _channel.write(toSend, this, _writeHandler); 
      }); 
     } 
     _writeLock.unlock(); 
    } 
} 

그런 다음 클라이언트에서 :