【问题标题】:Java NIO sockets: the server doesn't receive the second message over the same socketJava NIO 套接字:服务器没有通过同一个套接字接收第二条消息
【发布时间】:2019-11-25 15:06:50
【问题描述】:

我有使用 Java NIO 套接字构建的简单服务器和客户端。这个想法是客户端向服务器发送5,服务器回复1。然后,客户端再次使用同一个套接字发送1,服务器应该再次回复5

但是,服务器没有收到第二条消息。这是我的实现:

Server.java

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;

public class Server {

    public static void main(String[] args) throws IOException {
        Selector selector = Selector.open();
        ServerSocketChannel serverChannel = ServerSocketChannel.open();
        serverChannel.configureBlocking(false);
        serverChannel.bind(new InetSocketAddress(4444));
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            if (selector.select() > 0) {
                for (SelectionKey key : selector.selectedKeys()) {
                    if (key.isReadable()) {
                        SocketChannel clientChannel = (SocketChannel) key.channel();
                        ByteBuffer buffer = ByteBuffer.allocate(1);
                        clientChannel.read(buffer);
                        System.out.println("Received: " + buffer.array()[0]);
                        clientChannel.write(ByteBuffer.wrap(new byte[]{1}));
                        System.out.println("Replied: 1");
                    }
                    if (key.isAcceptable()) {
                        SocketChannel channel = serverChannel.accept();
                        if (channel != null) {
                            channel.configureBlocking(false);
                            channel.register(selector, SelectionKey.OP_READ);
                            System.out.println("Accepted");
                        }
                    }
                }
            }
        }
    }
}

Client.java

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;

public class Client {

    public static void main(String[] args) throws IOException {
        Selector selector = Selector.open();
        SocketChannel sc = SocketChannel.open();
        sc.configureBlocking(false);
        sc.connect(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 4444));
        sc.register(selector, SelectionKey.OP_CONNECT);

        while (true) {
            if (selector.select() > 0) {
                for (SelectionKey key : selector.selectedKeys()) {
                    SocketChannel channel = (SocketChannel) key.channel();
                    if (key.isConnectable()) {
                        while (channel.isConnectionPending()) {
                            channel.finishConnect();
                        }
                        key.interestOps(SelectionKey.OP_WRITE);
                        System.out.println("Connected");
                    }
                    if (key.isWritable()) {
                        channel.write(ByteBuffer.wrap(new byte[] { 5 }));
                        key.interestOps(SelectionKey.OP_READ);
                        System.out.println("Sending: 5");
                    }
                    if (key.isReadable()) {
                        ByteBuffer buffer = ByteBuffer.allocate(1);
                        channel.read(buffer);
                        System.out.println("Received: " + buffer.array()[0]);
                        key.interestOps(SelectionKey.OP_WRITE);
                    }
                }
            }
        }
    }
}

服务器输出

Accepted
Received: 5
Replied: 1

客户端输出

Connected
Sending: 5
Received: 1
Sending: 5

【问题讨论】:

    标签: java sockets


    【解决方案1】:

    我在这里找到了解决问题的方法:https://stackoverflow.com/a/9940133/4167198

    select() 返回已更改的键数。因此,如果一个密钥在 select() 调用之前已经准备好,那么它可能会返回 0,但 selectedKeys 可能是非空的。

    所以检查select()是否返回大于0是没有必要的。

    Server.java

    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.*;
    
    public class Server {
    
        public static void main(String[] args) throws IOException {
            Selector selector = Selector.open();
            ServerSocketChannel serverChannel = ServerSocketChannel.open();
            serverChannel.configureBlocking(false);
            serverChannel.bind(new InetSocketAddress(4444));
            serverChannel.register(selector, SelectionKey.OP_ACCEPT);
    
            while (true) {
                selector.select();
                for (SelectionKey key : selector.selectedKeys()) {
                    if (key.isReadable()) {
                        SocketChannel clientChannel = (SocketChannel) key.channel();
                        ByteBuffer buffer = ByteBuffer.allocate(1);
                        clientChannel.read(buffer);
                        System.out.println("Received: " + buffer.array()[0]);
                        clientChannel.write(ByteBuffer.wrap(new byte[]{1}));
                        System.out.println("Replied: 1");
                    }
                    if (key.isAcceptable()) {
                        SocketChannel channel = serverChannel.accept();
                        if (channel != null) {
                            channel.configureBlocking(false);
                            channel.register(selector, SelectionKey.OP_READ);
                            System.out.println("Accepted");
                        }
                    }
                }
            }
        }
    }
    

    Client.java

    import java.io.IOException;
    import java.net.InetAddress;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.SelectionKey;
    import java.nio.channels.Selector;
    import java.nio.channels.SocketChannel;
    
    public class Client {
    
        public static void main(String[] args) throws IOException {
            Selector selector = Selector.open();
            SocketChannel sc = SocketChannel.open();
            sc.configureBlocking(false);
            sc.connect(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 4444));
            sc.register(selector, SelectionKey.OP_CONNECT);
    
            while (true) {
                selector.select();
                for (SelectionKey key : selector.selectedKeys()) {
                    SocketChannel channel = (SocketChannel) key.channel();
                    if (key.isConnectable()) {
                        while (channel.isConnectionPending()) {
                            channel.finishConnect();
                        }
                        key.interestOps(SelectionKey.OP_WRITE);
                        System.out.println("Connected");
                    }
                    if (key.isWritable()) {
                        channel.write(ByteBuffer.wrap(new byte[] { 5 }));
                        key.interestOps(SelectionKey.OP_READ);
                        System.out.println("Sending: 5");
                    }
                    if (key.isReadable()) {
                        ByteBuffer buffer = ByteBuffer.allocate(1);
                        channel.read(buffer);
                        System.out.println("Received: " + buffer.array()[0]);
                        key.interestOps(SelectionKey.OP_WRITE);
                    }
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-05
      • 1970-01-01
      • 2021-08-22
      • 2021-03-30
      • 1970-01-01
      相关资源
      最近更新 更多