클라이언트간에 메시지를 교환하는 서버를 작성하고 있습니다. 해결해야 할 한 가지 문제는 클라이언트가 닫힐 때 채널을 해제하는 방법입니다. 내가하는 일은 all-Clients 맵이 모니터되는 모니터 스레드를 시작하고 write()를 시도 할 때 예외가 감지되면 채널을 제거()하려고 시도하는 것입니다. 그러나 클라이언트를 닫은 후에는 모니터 스레드의 write() 메서드가 예외를 throw하지 않으므로 쓸모없는 채널이 해제되지 않습니다. 왜 그런지 알아? TCP 소켓에 쓰기SocketChannel의 write() 메서드는해야 할 때 예외를 throw하지 않습니다.
public class ServerMonitor extends Thread{
private Map<String, SocketChannel> allClients;
private Set set;
private Iterator it;
private Entry entry;
private SocketChannel channel;
private ByteBuffer buf;
public ServerMonitor(Map<String, SocketChannel> allClients) {
this.allClients = allClients;
buf = ByteBuffer.allocateDirect(10);
byte b = 0;
buf.put(b);
buf.flip();
}
public void run(){
while(true) {
if(!allClients.isEmpty()) {
set = allClients.entrySet();
it = set.iterator();
while(it.hasNext()) {
entry = (Entry) it.next();
channel = (SocketChannel) entry.getValue();
try{
channel.write(buf);
} catch(Exception e) {
allClients.remove(entry.getKey());
//set.remove(entry);
}
}
}
try {
Thread.sleep(1000 * 5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
'this.allClients = allClients; '<- 당신은 정말 당신이 무엇을하고 있는지 알지 못한다면 이것은 매우 위험하다 ... 호출자가지도를 수정하는 경우, 클래스'지도 변경 사항을 볼 것이다! 'ConcurrentModificationException'을위한 좋은 소스 ... – fge
@fge 이것을 수행하고 싶습니다 .allClients = allClients; 왜냐하면 모니터 스레드가 바이트를 쓸 수없는 채널을 발견했을 때 소스 allClients (쓸모없는 채널 해제)를 수정해야하기 때문입니다. – dastan