문제

안녕하세요 저는 간단한 Java Nio 서버를 구현하려고합니다. Socketchannel을 선택기에 등록합니다. 따라서 고객의 말을 듣고 응답을 돌려 보내고 싶습니다. Socketchannel이 선택기에 등록 된 후 클라이언트 (NIO)가 일부 데이터를 보내더라도 서버는 읽을 수 없습니다. Howerver 생성 된 키가 여전히 반복되고 있습니다.

자세한보기 : 서버 측 :

**First thread**:

public void run () {while (true) {

    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    serverSocketChannel.configureBlocking(true);
    serverSocketChannel.socket().bind(inetAdressOfServer);
    SocketChannel clientChannel = serverSocketChannel.accept();
    new Listener("").addSocketChannel(clientChannel);

}}

**Second Thread**:

    static Selector selector = Selector.open();
    public boolean addSocketChannel(SocketChannel clientChannel) {

        SelectionKey key = clientSocketChannel.register(selector, selector.OP_READ|SelectionKey.OP_WRITE);              
        key.attach(new ChannelCallback(clientSocketChannel));
        return key.isValid();
    }

    public void run() {

        Set keysSet = selector.keys();
        Iterator i = keysSet.iterator();        
        while (i.hasNext()) {
            SelectionKey key = (SelectionKey) i.next();
        }

        if (key.isReadable()) {
            //read and do something
        }
    }



Client Side:

Socket socket = new Socket(serverIP, serverPort);    
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());    
dos.writeBytes(str + "\n");

NB : 단일 스레드에서 완료되면 동일한 프로그램이 작동하지만 위에서 언급 한 방식으로 구현하면 클라이언트의 말을 듣지 않습니다. 이 문제를 해결하도록 도와주세요.

도움이 되었습니까?

해결책

당신이 그곳에서 한 일을 보는 것은 매우 어렵지만 "두 번째 스레드"로 표시 한 내용은 두 스레드에서 사용되는 것처럼 보입니다 (구현에 대한 일부 혼란 Runnable/확장 Thread 그리고 실제 실?). 특히, 나는 추측하고있다 new Listener 스레드를 구성하고 시작합니다. 그런 다음 전화하고 있습니다 addSocketChannel 첫 번째 스레드에서. 따라서 인종 조건이 있습니다.

또한 만드는 것은 나쁜 생각입니다 selector 공전.

다른 팁

다른 스레드에서 읽는 작품을 읽으십시오. 코드의 명백한 문제는 다음과 같습니다.

public void run() {
    Set keysSet = selector.keys();

여기에서 반복자에서 키 세트를 가져 오지만 선택기에서 select () 또는 selectNow ()를 수행하는 코드는 없으므로이 세트는 항상 비어 있습니다.

    Iterator i = keysSet.iterator();        
    while (i.hasNext()) {
        SelectionKey key = (SelectionKey) i.next();
    }
    if (key.isReadable()) {
        //read and do something
    }
}

이렇게하면 컴파일되지 않으며 키에서 '읽기'확인은 while 블록 내부에서 수행되어야합니다.

SelectionKey key = clientSocketChannel.register(selector,
                                                SelectionKey.OP_READ | 
                                                SelectionKey.OP_WRITE);              

두 가지 문제 :이 작업을 수행하기 전에 채널을 차단 모드로 설정해야하며 SelectKey.op_write가 선택을 실행할 때마다 키를 반환하려고하지 않으면 설정되지 않아야합니다.

실제로 쓰기를 계획하는 경우 selectionkey.op_write 만 설정해야합니다.

마지막으로, 여기에 두 개의 스레드를 사용하는 것은 매우 독창적입니다. 이를 수행하는 권장 방법은 serversocketchanchann을 OP_ACCEPT를 사용하여 선택기에 등록하고 읽기/쓰기와 동일한 스레드의 서버 소켓에서 수락을 실행하는 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top