如何在Java Nio中为多个消息使用相同的客户端实例

时间:2014-12-15 13:51:03

标签: java client-server nio

我在下面使用Java Nio进行客户端服务器通信是客户端和服务器的代码。

服务器:

public class BufferChannelExample {
    private static String clientChannel = "clientChannel";
    private static String serverChannel = "serverChannel";
    private static String channelType = "channelType";
    private static Selector selector = null;
    static BufferChannelExample bufferChannelExample = null;
    static int port1 = 1114;
    //static String localhost1 = "192.168.1.35";
    static String localhost1 = "192.168.1.88";
    ByteBuffer buffer;
    static String msgFromClient = "";
    static MsgSaver msgSaver;
    public static void main(String[] args) {

//      readFileChannel();
        //msgSaver = new MsgSaver();
        bufferChannelExample = new BufferChannelExample();
        serverSocketExample();

    }

    public static void writeToChannels() {

        if(selector == null)
            return;
        if(!selector.isOpen())
            return;
        Set multipleKeys = selector.keys(); 
        System.out.println("multipleKeys.size() : "+multipleKeys.size());
        for (int i = 0; i < multipleKeys.size(); i++) {
            System.out.println("multipleKeys: "+multipleKeys.toString());
        }

        MulticastSocket multicastSocket = null;

        try {
            multicastSocket = new MulticastSocket(port1);

        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        Iterator<SelectionKey> mkIterator = multipleKeys.iterator();
        while (mkIterator.hasNext()) {
            SelectionKey sKey = mkIterator.next();

            //                                  System.out.println("mk rAddr : "+((SocketChannel)sKey.channel()).getRemoteAddress().toString());
            //                                  if(sKey == key){
//          if((sKey.readyOps() & SelectionKey.OP_ACCEPT) != SelectionKey.OP_ACCEPT){
            if(((Map<?, ?>) sKey.attachment()).get(channelType).equals(
                    clientChannel)){
                 System.out.println("isWritable() --- > "+sKey.isWritable());
                 System.out.println("RemoteSocketAddress : "+((SocketChannel)sKey.channel()).socket().getRemoteSocketAddress());
                // write something to the new created client
                 CharBuffer buffer;
                 if(msgFromClient.equalsIgnoreCase(""))
                 {
                  buffer = CharBuffer.wrap("Hello client new!!! ---stop");
                  System.out.println("if--");
                 }
                 else {

                     Iterator iter = multipleKeys.iterator();
                     while (iter.hasNext()) {
                       System.out.println(iter.next());
                     }

                      buffer = CharBuffer.wrap(msgFromClient);
                      System.out.println("else--");

                }

                //System.out.println("msgFromClient----"+msgSaver.getMsg());
                while (buffer.hasRemaining()) {

                    try {
                        ((SocketChannel)sKey.channel()).write(Charset.defaultCharset()
                                .encode (buffer)); 
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                buffer.clear();         
            }
            //                                  }
        }

    }

    private static void serverSocketExample() {
        ArrayList<String> remoteAddressArray = new ArrayList<String>();
        ServerSocketChannel channel1;
        try { 
            channel1 = ServerSocketChannel.open();
            channel1.socket().bind(new InetSocketAddress(localhost1, port1));
            channel1.configureBlocking(false);

            // create a selector that will by used for multiplexing. The selector
            // registers the socketserverchannel as
            // well as all socketchannels that are created
            selector = Selector.open();

            // register the serversocketchannel with the selector. The OP_ACCEPT
            // option marks
            // a selection key as ready when the channel accepts a new connection.
            // When the
            // socket server accepts a connection this key is added to the list of
            // selected keys of the selector.
            // when asked for the selected keys, this key is returned and hence we
            // know that a new connection has been accepted.
            SelectionKey socketServerSelectionKey = channel1.register(selector,
                    SelectionKey.OP_ACCEPT);
            // set property in the key that identifies the channel
            // Map<String, String=""> properties = new HashMap<string, string="">();
            Map<String, String> properties = new HashMap<String, String>();
            properties.put(channelType, serverChannel);
            socketServerSelectionKey.attach(properties);
            // wait for the selected keys
            for (;;) {
//              System.out.println("waiting for keys");
                // the select method is a blocking method which returns when atleast
                // one of the registered
                // channel is selected. In this example, when the socket accepts a
                // new connection, this method
                // will return. Once a socketclient is added to the list of
                // registered channels, then this method
                // would also return when one of the clients has data to be read or
                // written. It is also possible to perform a nonblocking select
                // using the selectNow() function.
                // We can also specify the maximum time for which a select function
                // can be blocked using the select(long timeout) function.
                if (selector.select() == 0)
                    continue;
                // the select method returns with a list of selected keys
                Set<SelectionKey> selectedKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectedKeys.iterator();
                while (iterator.hasNext()) {
                    SelectionKey key = iterator.next();
//                  System.out.println("SelectionKey "+key.toString());
                    // the selection key could either by the socketserver informing
                    // that a new connection has been made, or
                    // a socket client that is ready for read/write
                    // we use the properties object attached to the channel to find
                    // out the type of channel.
                    if (((Map<?, ?>) key.attachment()).get(channelType).equals(
                            serverChannel)) {
                        // a new connection has been obtained. This channel is
                        // therefore a socket server.
                        ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key
                                .channel();
                        // accept the new connection on the server socket. Since the
                        // server socket channel is marked as non blocking
                        // this channel will return null if no client is connected.
                        SocketChannel clientSocketChannel = serverSocketChannel
                                .accept();

                        if (clientSocketChannel != null) {
                            // set the client connection to be non blocking
                            clientSocketChannel.configureBlocking(false);
                            SelectionKey clientKey = clientSocketChannel.register(
                                    selector, SelectionKey.OP_READ| SelectionKey.OP_WRITE);
                            Map<String, String> clientproperties = new HashMap<String, String>();
                            clientproperties.put(channelType, clientChannel);
                            clientKey.attach(clientproperties);

                            // write something to the new created client
                            CharBuffer buffer = CharBuffer.wrap("Hello client from server");
                            while (buffer.hasRemaining()) {
//                              clientSocketChannel.write(Charset.defaultCharset()
//                                      .encode(buffer));

                                clientSocketChannel.write(Charset.defaultCharset()
                                        .encode(buffer));

                            }
                            buffer.clear();
                        }

                    } else {
                        // data is available for read
                        // buffer for reading
                        ByteBuffer buffer = ByteBuffer.allocate(100); 
                        SocketChannel clientChannel = (SocketChannel) key.channel();    
                        int bytesRead = 0;
                        if (key.isReadable()) {
                            // the channel is non blocking so keep it open till the
                            // count is >=0
                            if ((bytesRead = clientChannel.read(buffer)) > 0) {
                                buffer.flip();
//                              System.out.println("message from client ---> "+Charset.defaultCharset().decode(
//                                      buffer));
                                msgFromClient = Charset.defaultCharset().decode(buffer).toString();
                                //msgSaver.setMsg(Charset.defaultCharset().decode(buffer).toString());
                                System.out.println("msgFromClient111----"+Charset.defaultCharset().decode(buffer).toString());
                                writeToChannels(); 
//                              if(th == null){
//                               th = new Thread(new NewRunnable());
//                               th.start();
//                              }

                                 buffer.clear();
                            }
                            if (bytesRead < 0) {
                                // the key is automatically invalidated once the
                                // channel is closed
                                clientChannel.close();
                            }
                        }

                    }

                    // once a key is handled, it needs to be removed
                    iterator.remove();

                }

            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    static Thread th = null;




}



}

客户端:

公共类ExampleClient2 {

public static void main(String[] args) throws IOException,
InterruptedException {
    int port = 1114;
    SocketChannel channel = SocketChannel.open();


    // we open this channel in non blocking mode
    channel.configureBlocking(false);
    channel.connect(new InetSocketAddress("192.168.1.88", port));

    if(!channel.isConnected())
    {
        while (!channel.finishConnect()) {
            System.out.println("still connecting");
        }
    }
    System.out.println("connected...");


    while (true) {
        // see if any message has been received
        ByteBuffer bufferA = ByteBuffer.allocate(60);
        int count = 0;
        String message = "";
        while ((count = channel.read(bufferA)) > 0) {
            // flip the buffer to start reading
            bufferA.flip();
            message += Charset.defaultCharset().decode(bufferA);

        }

        if (message.length() > 0) {
            System.out.println("message " + message); 
            if(message.contains("stop"))
            {
                System.out.println("Has stop messages");
                //                  break;
            }
            else
            {
                // write some data into the channel
                CharBuffer buffer = CharBuffer.wrap("Hello Server stop from client2 from 88");
                while (buffer.hasRemaining()) {
                    channel.write(Charset.defaultCharset().encode(buffer));
                }
            }
            message = "";
        }

    }
}

}

如果我从同一客户端请求服务器两次,服务器将视为新客户端并创建新连接。如何检测消息来自旧客户端,而不需要创建新连接。

感谢。

1 个答案:

答案 0 :(得分:0)

您可以在应用程序中引入HTTP会话管理,然后根据会话ID跟踪每个客户端请求。然后,您可以让您的应用程序适应这种情况。

如果您的服务器使用Servlet技术,则添加Servlet过滤器以拦截所有传入请求会更加容易。