Сервер UDP показывает NotYetConnectedException при попытке чтения () из канала в буфер - PullRequest
0 голосов
/ 22 сентября 2019

Я пытаюсь прочитать из DatagramChannel cchannel_dtg в буфер inBuffer.

Я использую вызов select () для перебора ключей и соответствующих им каналов UDP, для чтения и записи.У меня также есть подобный кусок кода для TCP, который работает отлично, принимает много клиентов и возвращает их сообщения.

Однако, для этого фрагмента кода UDP, он терпит неудачу в строке bytesRecv = cchannel_dtg.read(inBuffer); из-за чтения () вызов (во время выполнения, когда я пытаюсь отправить сообщение со стороны клиента, он компилируется нормально).Исключение: java.nio.channels.NotYetConnectedException.

Я попытался выполнить вызов receive () вместо read (), который возвращает адрес принимающего клиента, но затем он блокировал некоторые другие соединения и взаимодействие сервера с клиентом не было удовлетворительным.

Кто-нибудь знает причину или решение?

public class SelectServer {
    public static int BUFFERSIZE = 32;
    public static void main(String args[]) throws Exception 
    {
        if (args.length != 1)
        {
            System.out.println("Usage: UDPServer <Listening Port>");
            System.exit(1);
        }

        // Initialize buffers and coders for channel receive and send
        String line = "";

        //Encoder and decoders between bytes<->chars
        Charset charset = Charset.forName( "us-ascii" ); //For converting 16-bit unicode characters to bytes.
        CharsetDecoder decoder = charset.newDecoder();  // Transform a sequence of bytes into a sequence of 16-bit Unicode characters.
        CharsetEncoder encoder = charset.newEncoder(); // Transform 16-bit Unicode characters into a bytes.

        ByteBuffer inBuffer = null; //Buffer to send data
        CharBuffer outBuffer = null; //Buffer to convert inbuffer's bytes to chars
        int bytesSent, bytesRecv;     // number of bytes sent or received - for error checking if msg was delivered to client

        // Initialize the selector
        Selector selector = Selector.open(); //Can examine one or more Java NIO Channel instances, 
                                             // and determine which channels are ready for e.g. reading or writing.
                                             // This way a single thread can manage multiple channels,
                                             // and thus multiple network connections.


        /**                   TCP CHANNEL CREATION                    */

        // Create a server channel and make it non-blocking
        ServerSocketChannel tcp_channel = ServerSocketChannel.open(); //tcp_channel that can listen for incoming TCP connections, 
                                                                  // just like a ServerSocket in standard Java Networking.
        tcp_channel.configureBlocking(false); //Adjusts this channel's blocking mode.

        // Get the port number and bind the socket
        InetSocketAddress isa1 = new InetSocketAddress(Integer.parseInt(args[0])); //Socket Address with specific port and wildcard IP address.
        tcp_channel.socket().bind(isa1); //Assign port and IP wildcard address to socket.

        // Register that the server selector is interested in connection requests
        tcp_channel.register(selector, SelectionKey.OP_ACCEPT); 

        /**                   UDP CHANNEL CREATION                    */
        //UDP Server
        DatagramChannel udp_channel = DatagramChannel.open();
        udp_channel.configureBlocking(false);
        InetSocketAddress isa2 = new InetSocketAddress(Integer.parseInt(args[0]));
        udp_channel.socket().bind(isa2);
        udp_channel.register(selector, SelectionKey.OP_READ); 


        // Wait for something happen among all registered sockets
        try {
            boolean terminated = false;
            while (!terminated) 
            {
                if (selector.select(500) < 0) //500miliseconds
                {
                    System.out.println("select() failed");
                    System.exit(1);
                }

                // Get set of ready sockets
                Set readyKeys = selector.selectedKeys(); //selector's selected keys set
                Iterator readyItor = readyKeys.iterator(); 

                // Walk through the ready set
                while (readyItor.hasNext()) 
                {
                    // Get 1 key from set {key,key,key..}
                    SelectionKey key = (SelectionKey)readyItor.next(); 

                    // Remove current key entry from iteration because we saved that key in a variable "key"
                    readyItor.remove();

                    // Accept new connections, if any
                    if (key.isAcceptable()) //if socket is accepting connections & has some to accept
                    {

                        SocketChannel cchannel = ((ServerSocketChannel)key.channel()).accept();
                        cchannel.configureBlocking(false);
                        System.out.println("Accept conncection from " + cchannel.socket().toString());

                        // Register the new connection for read operation
                        cchannel.register(selector, SelectionKey.OP_READ);
                    } 
                    else 
                    {   
                        SocketChannel cchannel;
                        DatagramChannel cchannel_dtg;

                        try{
                            cchannel = (SocketChannel)key.channel();
                            System.out.println("Connection coming from TCP server");

                            if (key.isReadable())
                            {
                                Socket socket = cchannel.socket();

                                // Open input and output streams (Receive bytes but send chars)
                                inBuffer = ByteBuffer.allocateDirect(BUFFERSIZE); //Size of outBuffer to accomodate BUFFERSIZE bytes to receive.
                                outBuffer = CharBuffer.allocate(BUFFERSIZE); //Size the inBuffer to accomodate BUFFERSIZE bytes to send

                                // Read from socket
                                bytesRecv = cchannel.read(inBuffer);
                                if (bytesRecv <= 0)
                                {
                                    System.out.println("read() error, or connection closed");
                                    key.cancel();  // deregister the socket
                                    continue;
                                }

                                inBuffer.flip();      // make buffer available  
                                decoder.decode(inBuffer, outBuffer, false);
                                outBuffer.flip();
                                line = outBuffer.toString();
                                System.out.println("Client: " + line);

                                // Echo the message back
                                inBuffer.flip();
                                bytesSent = cchannel.write(inBuffer); //write bytes to socket
                                if (bytesSent != bytesRecv)
                                {
                                    System.out.println("write() error, or connection closed");
                                    key.cancel();  // deregister the socket
                                    continue;
                                }

                                if (line.equals("terminate\n"))
                                    terminated = true;
                         }


                        }catch (ClassCastException e){}

                        try{
                            cchannel_dtg = (DatagramChannel)key.channel();
                            System.out.println("Connection coming from UDP server");

                            if (key.isReadable())
                            {
                                // Declare a UDP server socket
                                DatagramSocket echoServer = cchannel_dtg.socket();

                                if (args.length != 1)
                                {
                                    System.out.println("Usage: UDPServer <Listening Port>");
                                    System.exit(1);
                                }

                                // Try to open a server socket on the given port
                                // Note that we can't choose a port less than 1023 if we are not
                                // privileged users (root)

                                try {
                                    // As long as we receive data, echo that data back to the client.

                                        inBuffer = ByteBuffer.allocateDirect(BUFFERSIZE);
                                        outBuffer = CharBuffer.allocate(BUFFERSIZE); //Size the inBuffer to accomodate BUFFERSIZE bytes to send

                                        // Receive data into inBuffer from the socket
                                        bytesRecv = cchannel_dtg.read(inBuffer); 

                                        if (bytesRecv <= 0)
                                        {
                                            System.out.println("read() error, or connection closed");
                                            key.cancel();  // deregister the socket
                                            continue;
                                        }

                                        inBuffer.flip();      // make buffer available  
                                        decoder.decode(inBuffer, outBuffer, false);
                                        outBuffer.flip();
                                        line = outBuffer.toString();
                                        if(!line.equals("")){
                                        System.out.println("Client: " + line);
                                        }

                                        // Echo the message back

                                        inBuffer.flip();
                                        bytesSent = cchannel_dtg.write(inBuffer); //write bytes to socket

                                        if (bytesSent != bytesRecv)
                                        {
                                            System.out.println("write() error, or connection closed");
                                            key.cancel();  // deregister the socket
                                            continue;
                                        }


                                        if (line.equals("terminate\n")){terminated = true;}

                                }catch(IOException e) {
                                        System.out.println(e);
                                }
                            }

                            } catch(ClassCastException e){}

                    }
                } // end of while (readyItor.hasNext()) 
            } // end of while (!terminated)
        }catch(IOException e){System.out.println(e);}

        // close all connections
        Set keys = selector.keys();
        Iterator itr = keys.iterator();
        while (itr.hasNext()) 
        {
            SelectionKey key = (SelectionKey)itr.next();
            //itr.remove();
            if (key.isAcceptable()){
                try{((ServerSocketChannel)key.channel()).socket().close();}catch(ClassCastException e){}
                try{((DatagramChannel)key.channel()).socket().close();}catch(ClassCastException e){}
            }
            else if (key.isValid()){
                try{((SocketChannel)key.channel()).socket().close();}catch(ClassCastException e){}
                try{((DatagramChannel)key.channel()).socket().close();}catch(ClassCastException e){}
            }

        }
    }
}          ```          
...