안녕하세요. 저는 잘 확장되고 수천 개의 클라이언트에 서비스를 제공하는 서버 프로그램을 만들고 있습니다. 문제는 Apache MINA가 너무 무거워서 사용하지 않기로 결정하고 대신 내 고객 클라이언트를 작성한 것입니다. Java에서 비동기 소켓 작업을 수행 한 적은 한 번도 없었지만 (C#을 사용하면 훨씬 쉽습니다.하지만이 프로젝트를 Java로 작성하는 것이 더 좋았습니다. 소켓 읽기 이외의 모든 작업에서이 프로젝트에 익숙하므로이 프로젝트를 사용하는 방법을 이해하려고 노력했습니다.) 스레드 풀이 올바르게 나를 위해 어렵습니다. Apache MINA 문서를 사용하여 작업을 수행하는 방법에 대한 아이디어를 얻었습니다. 두 가지 질문이 있습니다.Executors.newFixedThreadPool을 사용하는 비동기 Java NIO에 도움이 필요합니다.
- 스레드 풀이 올바르게 사용 되었습니까? Apache MINA의 기본 스레드 크기는 CPU 코어 수 +1입니다. 그러나 수천 명의 클라이언트를 수용하기 위해 실제로 코어 2 듀오에 3 스레드 스레드 풀을 사용해야합니까?
- 클라이언트로부터받은 각 메시지에 대해 두 번 버퍼를 다시 할당한다는 것은 알고 있습니다. 각 메시지는 두 개의 패킷으로, 한 개의 헤더는 상수 4 바이트이고 그 길이는 헤더에 지정된 내용 패킷입니다. 버퍼 오버런을 검사하는 고정 된 크기의 버퍼를 사용하는 쉬운 방법이 있습니까? 그래도 동작은 동일하지만 버퍼를 끊임없이 재 할당 할 필요가 없습니다.
private static final int THREADS = Runtime.getRuntime().availableProcessors() + 1; private ServerSocket socket; private ExecutorService threadPool; private int port; public ClientListener(int port) { this.port = port; threadPool = Executors.newFixedThreadPool(THREADS); } public void init() { try { socket = new ServerSocket(port); } catch (IOException ex) { } } public void run() { while (true) { try { ClientSession s = new ClientSession(socket.accept()); threadPool.execute(s); } catch (IOException ex) { } } }
대로 ClientSession 관련 코드 :
private Socket socket; private byte[] buffer; private boolean isHeader; public ClientSession(Socket socket) { this.socket = socket; this.buffer = new byte[4]; this.isHeader = true; } public void run() { InputStream in; try { in = socket.getInputStream(); out = socket.getOutputStream(); } catch (IOException ex) { return; } while (!socket.isClosed()) { try { int read = in.read(buffer); if (read == -1) break; receive(read); } catch (IOException ex) { break; } } } private void receive(int readBytes) { if (isHeader) { if (readBytes >= 4) { buffer = new byte[getPacketLength(buffer)]; isHeader = false; } else { System.out.println("Not enough data received from client " + socket.getInetAddress() + " to decode packet."); } } else { if (readBytes >= buffer.length) { processMessage(new LittleEndianByteArrayReader(decryptData(buffer)), this); buffer = new byte[4]; isHeader = true; } else { System.out.println("Not enough data received from client " + socket.getInetAddress() + " to decode packet (needed " + buffer.length + ", received " + readBytes + ")."); } } }
당신은하지 않습니다 여기
이 ClientListener에 대한 관련 코드입니다 : 여기ClientListener cl = new ClientListener(1234); cl.init(); new Thread(cl).start();
내가 리스너를 시작하는 방법 getPacketLength, processMessage, decrypt에 대한 코드를 알아야합니다. 데이터 및 클래스 LittleEndianByteArrayReader,하지만 꽤 그 메서드/클래스의 목적을 분명히 확신 해요.
무엇이 튀어 나오는지는 단지 당신이 예외를 삼키는 것입니다. 적어도 기록하십시오. – dogbane
이것은 단지 코드 스 니펫입니다. 실제 코드에서는 상세한 메시지와 함께 java.util.Logger를 사용하여 로그합니다. –
NIO를 전혀 사용하지 않으십니까? 당신은 Selector가 필요합니다. –