Java NIO (Linux를 실행하는) 서버에서 클라이언트로 여러 개의 큰 메시지를 빠르게 연속적으로 보내는 것이 좋지 않은 문제가 있습니다. 잘린 패킷. 메시지는 커야하며 문제가 발생하기 위해서는 매우 빠르게 보내야합니다. 여기에 내 코드가 무엇을하고 있는지 기본적입니다 (실제적인 코드를하지만, 더 또는 덜 무슨 일이 일어나고 있는지) : 그래서Java NIO : 대용량 메시지를 빨리 보내면 잘리는 패킷 및 데이터 손실이 발생합니다.
//-- setup stuff: --
Charset charset = Charset.forName("UTF-8");
CharsetEncoder encoder = charset.newEncoder();
String msg = "A very long message (let's say 20KB)...";
//-- inside loop to handle incoming connections: --
ServerSocketChannel ssc = (ServerSocketChannel)key.channel();
SocketChannel sc = ssc.accept();
sc.configureBlocking(false);
sc.socket().setTcpNoDelay(true);
sc.socket().setSendBufferSize(1024*1024);
//-- later, actual sending of messages: --
for (int n=0; n<20; n++){
ByteBuffer bb = encoder.encode(CharBuffer.wrap(msg+'\0'));
sc.write(bb);
bb.rewind();
}
, 패킷이 같은 루프에서 빨리 즉, (가능한 한 충분히 길고 보낸 경우 지연없이)으로, 다음 다른 쪽 끝에서 종종이 같은 온다 :
[COMPLETE PACKET 1]
[COMPLETE PACKET 2]
[COMPLETE PACKET 3]
[START OF PACKET 4][SOME OR ALL OF PACKET 5]
이 데이터 손실 및 패킷 함께 실행하기 시작 등이 예에서 패킷 (5)의 시작() 패킷 4의 시작과 동일한 메시지에 도착합니다. 메시지를 함께 실행하는 것만으로 끝나는 것이 아닙니다.
이것이 TCP 버퍼 또는 "창 크기"와 관련이 있거나 서버가 OS 또는 네트워크 어댑터보다 빠른 데이터를 제공하고 있다고 생각합니다. 그런데 어떻게 확인하고 그것을 방지합니까? sc.write() 사용 당 메시지 길이를 줄이지 만 반복 횟수를 늘리면 같은 문제가 발생합니다. 짧은 시간 내에 데이터 양에 문제가있는 것처럼 보입니다. 나는 sc.write()가 예외를 던지고있는 것을 보지 못합니다. (위의 예제에서 저는 검사하지 않지만 내 테스트에는 있습니다).
프로그래밍 방식으로 데이터가 아직 준비되지 않았는지 확인하고 지연을 넣고 준비 될 때까지 기다릴 수 있으면 행복 할 것입니다. 또한 "sc.socket() .setSendBufferSize (1024 * 1024);" 어떤 영향을 미치는지, 또는 Linux 측에서이를 조정해야 할 필요가 있다면. SocketChannel을 실제로 "플러시"할 수있는 방법이 있습니까? 절름발이 해결 방법으로, 내가 명시 적으로 10KB 이상의 메시지를 보내려고 할 때 버퍼링 된 모든 내용을 강제로 보내도록 시도 할 수 있습니다 (예 : 응용 프로그램에서 자주 사용하지 않음). 그러나 나는 버퍼 전송을 강제로 (또는 전송할 때까지 기다리는) 방법을 모른다. 어떤 도움을 주셔서 감사합니다!
예! 네트워크를 통해 데이터를 빠르게 보낼 수 있다고 기대하는 것은 합리적이지 않습니다. 차단하지 않으면 쓰기 결과를 테스트해야합니다. – erickson