1

I have have Tcp Server

public class SomeServer implements Runnable{


    private static final int BUFFER_SIZE = 4096;
    private Selector selector;
    private int port;
    private boolean runserver = true;
    private ServerSocketChannel mySocketChannel;
    private ServerSocket serverSocket;

    public SomeServer(int port) {
        this.port = port;
    }


    @Override
    public void run() {
        startServer();
    }

    private void startServer() {
        try {
            selector = Selector.open();
            InetAddress hostIP = InetAddress.getByName("127.0.0.1");
            mySocketChannel = ServerSocketChannel.open();
            serverSocket = mySocketChannel.socket();
            InetSocketAddress address = new InetSocketAddress(hostIP, port);
            log.info("Setting up SomeServer with on {} with port {} ", hostIP, port);
            serverSocket.bind(address);
            mySocketChannel.configureBlocking(false);
            int ops = mySocketChannel.validOps();
            mySocketChannel.register(selector, ops, null);
            while (runserver) {
                log.info("Server running");
                selector.select();
                Set<SelectionKey> selectedKeys = selector.selectedKeys();
                Iterator<SelectionKey> i = selectedKeys.iterator();

                while (i.hasNext()) {
                    SelectionKey key = i.next();

                    if (key.isAcceptable()) {
                        processAcceptEvent(mySocketChannel, key);
                    } else if (key.isReadable()) {
                        processReadEvent(key);
                    }
                    i.remove();
                }
            }

        } catch (Exception e) {
            log.error("Something gone wrong in SomeServer {}", e);
        }
    }

    private void processAcceptEvent(ServerSocketChannel mySocket, SelectionKey key) throws IOException {
        log.info("Connection Accepted...");
        // Accept the connection and make it non-blocking
        SocketChannel myClient = mySocket.accept();
        myClient.configureBlocking(false);
        // Register interest in reading this channel
        myClient.register(selector, SelectionKey.OP_READ);
    }

    private void processReadEvent(SelectionKey key) throws Exception {
        log.info("Inside processReadEvent...");
        // create a ServerSocketChannel to read the request
        SocketChannel myClient = (SocketChannel) key.channel();

        ByteBuffer myBuffer = ByteBuffer.allocate(BUFFER_SIZE);

        myBuffer.order(ByteOrder.BIG_ENDIAN);
        int radBytes= myClient.read(myBuffer);
        if(radBytes ==-1)
            return; //means connection is closed

        ByteBuffer responseBuffer = clone(execute(myBuffer));

        if(responseBuffer ==null){
            return;
        }
        int byteswritten = myClient.write(responseBuffer);
        log.info("bytesWritten...: {}", byteswritten);
    }

public ByteBuffer execute(ByteBuffer requestBuffer) throws Exception {
    final CharsetEncoder myEncoder = Charset.forName("ISO-8859-1").newEncoder();
    final byte END_OF_MESSAGE_BYTE = (byte) 0x2b;
    CharsetDecoder myDecoder = Charset.forName("ISO-8859-1").newDecoder();

    //Process Request
    final ByteBuffer processBuffer = clone(requestBuffer);
    // processBuffer.flip();
    int bufferSize = processBuffer.getInt();
    String request = myDecoder.decode(processBuffer).toString().trim();
    int requestLength=request.length();
    if(requestLength<8){
        log.info("Connection closed ");
        return null;
    }
    String firstName = request.substring(0,8);
    int requestBodyLength= requestLength-firstName.length();
    String command = request.substring(8,requestLength-1);

    processBuffer.flip();
    //Build-Response
    processBuffer.clear();
    String response="some response";
    int responselength = response.length()+firstName.length()+4;
    processBuffer.putInt(responselength);
    processBuffer.put(myEncoder.encode(CharBuffer.wrap(firstName)));
    processBuffer.put(myEncoder.encode(CharBuffer.wrap(response)));
    processBuffer.put(END_OF_MESSAGE_BYTE);
    processBuffer.flip();

    return processBuffer;
}

public static ByteBuffer clone(ByteBuffer original) {
    if(original == null)
        return null;
    ByteBuffer clone = ByteBuffer.allocate(original.capacity());
    original.rewind();//copy from the beginning
    clone.put(original);
    original.rewind();
    clone.flip();
    return clone;
}


}

Sending some message and except some response back

Client Side :Reading Response

     public class Mycleint {

 priavte SocketCahnnel mySocket;
 priavte String name;
 final byte END_OF_MESSAGE_BYTE = (byte) 0x2b;

public Mycleint (String name , InetSocketAddress inetAddress){
        this.name=name;
        mySocket = SocketChannel.open();
        mySocket.connect(inetAddress);

}

 private String sendRequest(String request) throws IOException {
            final CharsetEncoder myEncoder = Charset.forName("ISO-8859-1").newEncoder();
            int requestLength = 12 + request.length() + 1;
            ByteBuffer buffer = ByteBuffer.allocate(requestLength);
            buffer.order(ByteOrder.BIG_ENDIAN);
            buffer.putInt(requestLength);
            buffer.put(myEncoder.encode(CharBuffer.wrap(name)));
            buffer.put(myEncoder.encode(CharBuffer.wrap(request)));
            buffer.put();
            buffer.flip();
            mysocket.write(buffer);
            return readResponse();
    }

     private String readResponse(SocketChannel mySocket) throws IOException {

    CharsetDecoder myDecoder = Charset.forName("ISO-8859-1").newDecoder();
    ByteBuffer responseHeaderBuf = ByteBuffer.allocate(12);
    responseHeaderBuf.order(ByteOrder.BIG_ENDIAN);
    int bytesRead = 0;
    do {
        bytesRead = mySocket.read(responseHeaderBuf);
    } while (bytesRead != -1 && responseHeaderBuf.position() < 12);

    if (bytesRead == -1) {
        throw new IOException(" : Remote connection closed unexpectedly");
    }

        responseHeaderBuf.flip();
        int lengthField = responseHeaderBuf.getInt();
        int responseLength = lengthField - responseHeaderLength;
        String responseName = myDecoder.decode(responseHeaderBuf).toString();



        ByteBuffer responseBuf = ByteBuffer.allocate(responseLength);
        do {
            bytesRead = mySocket.read(responseBuf);
        } while (bytesRead != -1 && responseBuf.position() < responseLength);

        if (bytesRead == -1) {
            throw new IOException(name + " : Remote connection closed unexpectedly");
        }
        responseBuf.flip();


        if (responseBuf.get(responseBuf.limit() - 1) == END_OF_MESSAGE_BYTE) {
            responseBuf.limit(responseBuf.limit() - 1);
        }
        String response = myDecoder.decode(responseBuf).toString();
        return response;

    }

}

I leave the SocketChannel open indefinitely in client side .

When I decode the response in client responseHeaderBuf.getInt(), It works correct during the first time. but second time the data get corrupted when i decode.

Also if a socket is used to send request everything works as expected,but i want to reuse the socket i created

Example, if server sent 28 processBuffer.putInt(28); client says it received responseHeaderBuf.getInt()--> 721420288 ,

Could some one help and tell me what I'm doing wrong.

edwin
  • 7,985
  • 10
  • 51
  • 82
  • 6
    721420288 = 0x2b000000, which is the little-endian form of 28. You haven’t shown your client’s sending code, but I suspect your client is calling `order(ByteOrder.LITTLE_ENDIAN)` on its send buffer. – VGR Aug 26 '18 at 22:34
  • @VGR I added full client code – edwin Aug 27 '18 at 09:04
  • @VGR you can see `buffer.order(ByteOrder.BIG_ENDIAN);` in client while read and write. also server in server too ,I had a doubt around `clone` method in server code i removed i tried still gets the same problem – edwin Aug 27 '18 at 10:38
  • From the [ByteBuffer documentation](https://docs.oracle.com/javase/10/docs/api/java/nio/ByteBuffer.html): “The initial order of a byte buffer is always `BIG_ENDIAN`.” You would be better off simply removing all calls to the `order` method. – VGR Aug 27 '18 at 13:38
  • @VGR ,Tried your suggestion with `order ` that not working,The interesting part is if I open new socket on each `sendRequest` call everything works as expected – edwin Aug 27 '18 at 14:02
  • @VGR finally found the culprit `clone` method was changing the order of buffer in server.I use the same buffer to read write that works.Thanks for your tip – edwin Aug 29 '18 at 22:22
  • The `clone(ByteBuffer)` method shown in your question does not appear to change the byte order. – VGR Aug 29 '18 at 22:24

0 Answers0