Простая клиент-серверная программа с каналами NIO

1

SOLVED Если кому-то будет интересно, я могу отредактировать этот пост с правильными данными. Просто оставьте комментарий.


В качестве моего задания мне пришлось создать простой сервер и клиент с использованием неблокирующих каналов и селекторов. В основном это должно либо эхо-сообщение, написанное клиентом, либо добавление двух чисел (также предоставляемых клиентом).

Моя проблема в том, что я получаю ошибки в точке, где сообщение должно быть эхом от сервера. Я проверил, получает ли msg метод writeResponse, и он это делает. Итак, когда проблема начинается.

Спасибо всем заранее !

Ошибки, которые я получаю:

   java.io.IOException: An existing connection was forcibly closed by the remote host
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:218)
at sun.nio.ch.IOUtil.read(IOUtil.java:191)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:359)
at SimpleServer.serviceRequest(SimpleServer.java:89)
at SimpleServer.serviceConnections(SimpleServer.java:61)
at SimpleServer.<init>(SimpleServer.java:35)
at SimpleServer.main(SimpleServer.java:141)

Сервер:

  public class SimpleServer {

private ServerSocketChannel ssc = null; //for multiplexing
private Selector selector = null; //monitors channels

private static Charset charset = Charset.defaultCharset();//encoding
private static final int BSIZE = 1024;//buffer size

private ByteBuffer bbuf = ByteBuffer.allocate(BSIZE);
private StringBuffer reqString = new StringBuffer();

public SimpleServer(String host, int port) {
    try {           
        ssc = ServerSocketChannel.open();
        ssc.configureBlocking(false);
        ssc.socket().bind(new InetSocketAddress(host, port));           
        selector = Selector.open(); //selector initiation           
        ssc.register(selector,  SelectionKey.OP_ACCEPT);  //registering communication channel           
    } catch(Exception exc) {
        exc.printStackTrace();
        System.out.println(1);
    }

    System.out.println("Server started and is ready for requests");
    serviceConnections();
}//constructor

private void serviceConnections() {     
    boolean serverIsRunning = true;     
    while(serverIsRunning) {
        try {

            selector.select();//waits for answer from selector              
            Set<SelectionKey> keys = selector.selectedKeys(); //set of keys
            Iterator<SelectionKey> iter = keys.iterator(); //iterration throught set of keys

            while(iter.hasNext()) {
                SelectionKey key = (SelectionKey) iter.next(); //obtain key
                iter.remove(); //remove, because we'd get it again

                if(key.isAcceptable()) {
                    SocketChannel cc = ssc.accept();//obtaining channel for communication
                    cc.configureBlocking(false);
                    cc.register(selector, SelectionKey.OP_READ); //registering selector for monitoring
                    continue;
                }

                if(key.isReadable()) { //channel with readable data
                    SocketChannel cc = (SocketChannel) key.channel();
                    serviceRequest(cc);
                    continue;
                }                   
            }//while loop

        } catch(Exception exc) {
            exc.printStackTrace();
            continue;
        }
    }//outer while loop     
}//serviceCconnection method    

private void serviceRequest(SocketChannel sc) {
    if(!sc.isOpen()) return;

    reqString.setLength(0);
    bbuf.clear();

    try {
        readLoop:
            while (true) {
                int n = sc.read(bbuf);                  
                if(n > 0) {
                    bbuf.flip();//set limit, return to beginning
                    CharBuffer cbuf = charset.decode(bbuf);
                    while(cbuf.hasRemaining()) {
                        char c = cbuf.get();
                        if (c == '\r' || c == '\n') break readLoop;
                        reqString.append(c);
                    }
                }
            }//while loop

    String[] req = reqString.toString().split(" ");
    String cmd = req[0];

    if (cmd.equals("bye")) { 
          sc.close();                      
          sc.socket().close();
      }
    else if(cmd.equals("echo"))

        writeResp(sc, reqString.toString());

    else if(cmd.equals("add"))
        writeResp(sc, Integer.parseInt(req[1]),Integer.parseInt( req[2]));
    } catch (Exception exc) {                  
        exc.printStackTrace();
        try { sc.close();
              sc.socket().close();
        } catch (Exception e) {}
    }
}//serviceRequest   

//overloaded methods
public void writeResp(SocketChannel sc, String msg) throws IOException {
    System.out.println(msg);
    ByteBuffer cbuf = charset.encode(CharBuffer.wrap(msg));
    cbuf = ByteBuffer.allocate(1024);
    cbuf.put(msg.getBytes());
    cbuf.rewind();
     sc.write(cbuf);
}//writeResp method

public void writeResp(SocketChannel sc, int i, int j) throws IOException, NumberFormatException {
    int ans = i + j;
    String resp = Integer.toString(ans);
    ByteBuffer cbuf = charset.encode(CharBuffer.wrap(resp));
    sc.write(cbuf);
}//write Resp method

public static void main(String[] args) {
    try {
        String host = "localhost";
        int port = 9998;
                new SimpleServer(host, port);
    } catch(Exception exc) {
        exc.printStackTrace();
        System.out.println(1);
    }
}//main
}//class

Мой клиент:

 public class SimpleClient {

private SocketChannel sc;   
private static Charset charset;
private StringBuffer reqString = new StringBuffer();
private ByteBuffer bb;
String msg;

public SimpleClient(String host, int port) throws IOException, InterruptedException {
    try {

        sc = SocketChannel.open();
        sc.configureBlocking(false);
        sc.connect(new InetSocketAddress(host, port));
        System.out.println("Connecting to the server...");

        while(!sc.finishConnect()) {
            System.out.println("Connection is being established...");
        }
    } catch (IOException exc) {
        System.out.println("IO exception");
        System.exit(1);
    }
    System.out.println("Connection Established!");

    makeRequest("echo Test input stream\n");
    Thread.sleep(500);
    readRequest();      
}//constructor

private void makeRequest(String req) throws IOException {
    System.out.println("Request: " + req);      
     bb = ByteBuffer.allocate(1024);
     bb.put(req.getBytes());
     bb.rewind();
     sc.write(bb);  
}//makeRequest method

public void readRequest() throws IOException, InterruptedException {        

    reqString.setLength(0);
    bb.clear();

    try {
        readLoop:       
        while (true) {      
            bb.clear();
            int readBytes = sc.read(bb);
            if(readBytes == 0){
                System.out.println("waiting for data");
            continue;
            }
            else if(readBytes == -1) {
                System.out.println("Server not responding");
                break;
            }
            else {
                bb.flip();
                CharBuffer cbuf = charset.decode(bb);
                while(cbuf.hasRemaining()) {
                    char c = cbuf.get();
                    if (c == '\r' || c == '\n') break readLoop;
                    reqString.append(c);
                }
            }
        }//while loop

    System.out.println(reqString.toString());
        } catch( Exception exc) {//while loop
            exc.printStackTrace();
        }
}//readRequest method   

public static void main(String[] args)  {
    try {
    new SimpleClient("localhost", 9998);
    }catch (IOException exc) {
        exc.printStackTrace();
    }catch(InterruptedException exc) {
        exc.printStackTrace();
    }
}//main method  
 }//class
Теги:
echo
nio
buffer
socketchannel

1 ответ

0

Если read() возвращает -1, это не означает, что "сервер не отвечает". Это означает, что сверстник закрыл соединение, и вы должны поступать аналогичным образом. Вместо этого вы не закрываете его вообще, поэтому операционная система выполняет сброс, поэтому ваш сервер получает это исключение.

  • 0
    Спасибо за ваш ответ, но я уже исправил свою программу. Если кому-то будет интересно, ошибка была вызвана несколькими причинами: 1. добавить значения должны быть преобразованы в удвоение, а не в int 2. отсутствие bufferedReader 3. Charset.defaultCharset (). Decode (bbuf) .toString (); следует использовать вместо того, что я сделал с добавлением.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню