2015-01-28 5 views
2

현재 연결을 청취하는 서버가 있습니다.이 서버는 1000ms마다 연결을 루프하고 들어오는 데이터를 수신합니다. InputStream 논 블로킹으로 만들기

public void readData(Connection c) throws IOException { 
    PacketBuffer readBuffer = new PacketBuffer(Server.PACKET_CAPACITY); 
    int packetSize = c.getIn().read(); 
    c.getIn().mark(packetSize); 
    byte[] buffer = new byte[packetSize]; 
    c.getIn().read(buffer, 0, buffer.length); 
    readBuffer.setBuffer(buffer); 
    packetHandler.addProcess(c, readBuffer); 
} 

나는 내 자신의 PacketBuffer을 사용하고 c.getIn가(). 차단하지 않습니다 (그건 내 연결의 InputStream입니다)) (읽을 수 있도록 나는 방법을 찾을 필요가있다. 현재 소켓은 500ms 타임 아웃으로 설정되어 있고, 서버는 그렇게 잘 돌아갈 것입니다. 내 문제는 누군가 자신의 프로그램을 만들어 자신의 최고 기록 또는 해킹 시도에 연결하려고 시도하는 경우 연결이 쓰여지지 않을 때 500ms 동안 스레드를 차단하는 쓸모없는 연결이 번들로되어 버립니다.

+1

이 코드는 손으로 직접 작성한 코드 대신 Netty의 작업처럼 들립니다. – chrylis

답변

3

다음과 같이 시도해 볼 수 있습니다. readData가 호출 될 때마다 바이트를 읽을 수 있는지 확인합니다. 을 사용하고 루프를 사용하면 스레드가 다시 잠자기 전에 모든 데이터를 처리하기를 원하기 때문입니다. 이렇게하면 x 밀리 초마다 하나만 읽는 경우 메시지가 백업되지 않습니다.

public void readData(Connection c) throws IOException { 
    while (c.getIn().available() > 0) { 
     int packetSize = c.getIn().read(); 
     c.getIn().mark(packetSize); 
     byte[] buffer = new byte[packetSize]; 
     c.getIn().read(buffer, 0, buffer.length); 
     PacketBuffer readBuffer = new PacketBuffer(Server.PACKET_CAPACITY); 
     readBuffer.setBuffer(buffer); 
     packetHandler.addProcess(c, readBuffer); 
    } 

나는 왜 마크 방법을 사용하는지 알지 못합니다. 나 한테 문제가있어.

실제로 전체 바이트 배열을 읽을 때까지 반환하지 않는 readFully() 스타일 메서드 (DataInputStream 참조)를 사용해야합니다. 일반 읽기는 보낸 사람이 전체 데이터 블록 (네트워크 패킷 크기 등으로 인해)을 보낸 경우에도 항상 "반환"할 수 있습니다.

0

수 없습니다. InputStreams가 블로킹하고 있습니다. 기간. 비 차단 모드가 실제로 언급 한 문제를 어떻게 해결할 수 있는지 보는 것은 어렵습니다. 나는 재 설계가 필요하다고 제안한다.

2

Java에서 서버를 구현하는 두 가지 고전적인 방법이 있습니다.

가장 오래된 방법은 연결된 각 클라이언트에 대해 읽기/쓰기 스레드 쌍을 사용하는 것입니다. 연결된 클라이언트가 많지 않은 소규모 서버의 경우 각 클라이언트가이를 관리하기 위해 두 개의 스레드가 필요하기 때문에 괜찮습니다. 많은 동시 클라이언트에게는 확장 성이 좋지 않습니다.

두 번째 및 더 새로운 방법은 java.nio.ServerSocketChannel, java.nio.SocketChanneljava.nio.Selector을 사용하는 것입니다. 이 세 클래스를 사용하면 단일 스레드에서 연결된 모든 클라이언트에 대한 모든 IO 작업을 관리 할 수 ​​있습니다. Herejava.nio 패키지를 사용하여 매우 기본적인 서버를 구현하는 방법에 대한 예입니다.

서버를 구현하는 훨씬 좋은 방법은 타사 프레임 워크를 사용하는 것입니다. 내가 과거에 사용한 훌륭한 도서관은 Netty입니다. 그것은 소켓의 모든 핵심적인 세부 사항을 처리하고 잘 비례하는 깨끗하고 간단한 API를 제공합니다.