Solved

Java nio write/read non-blocking socketchannel

Posted on 2011-09-15
15
3,050 Views
Last Modified: 2013-08-27
I need to write to the socketChannel and read from socket channel.
Could you please take a look at the following client code see what is the issue?
I have also included the serverSocket. GenericSocketServer. It’s basically echos the message that client sends.
Writing to socket and reading to socketchennel does seem to work.

Thank you

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;


public class ConnectAsync
{
    public static void main (String [] argv) throws IOException
        
    {
    	
    	// Create a non-blocking socket and check for connections
    	try {
    	    // Create a non-blocking socket channel on port 80
    	    SocketChannel sChannel = createSocketChannel("localhost", 20208);

    	    // Before the socket is usable, the connection must be completed
    	    // by calling finishConnect(), which is non-blocking
    	    System.out.println("finishConnect(): " + sChannel.finishConnect());
    	    while (!sChannel.finishConnect()) {
    	      System.out.println(" Do something else");
    	    
    	    }
    	    writeToChannel(sChannel);
 	       readFromChannel(sChannel);
    	    // Socket channel is now ready to use
    	    sChannel.close();
    	} catch (IOException e) {
    	}

    }
    private static void readFromChannel(SocketChannel socketChannel )
    {
    	 Charset charset = Charset.forName("ISO-8859-1");

    	ByteBuffer buf = ByteBuffer.allocate(48);
    	CharsetDecoder decoder = charset.newDecoder();


    	try {
			int bytesRead = socketChannel.read(buf);
		//	int bytesread = client.read(buffer);
	          if (bytesRead == -1) {
	            //key.cancel();
	        	  socketChannel.close();
	           // continue;
	          }
	         buf.flip();
	          String request = decoder.decode(buf).toString();
	          System.out.println("request: " + request);
	          buf.clear();

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

    }
    private static void writeToChannel(SocketChannel socketChannel )
    {
    	String newData = "New String to write to file..." + System.currentTimeMillis();

    	ByteBuffer buf = ByteBuffer.allocate(48);
    	buf.clear();
    	buf.put(newData.getBytes());

    	buf.flip();
    	while(buf.hasRemaining()) {
    		try {
				socketChannel.write(buf);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    		System.out.println("check 2");
    	}	

    }
    
    public static SocketChannel createSocketChannel(String hostName, int port) throws IOException {
        // Create a non-blocking socket channel
        SocketChannel sChannel = SocketChannel.open();
        sChannel.configureBlocking(false);

        // Send a connection request to the server; this method is non-blocking
        sChannel.connect(new InetSocketAddress(hostName, port));
        return sChannel;
    }

}






--------------Generic socket Server
import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class GenericSocketServer {

    
    public static void main(String args[]) {
        // declaration section:
        // declare a server socket and a client socket for the server
        // declare an input and an output stream
        ServerSocket echoServer = null;
        String line;
        DataInputStream is;
        PrintStream os;
        Socket clientSocket = null;
        // Try to open a server socket on port 9999
        // Note that we can't choose a port less than 1023 if we are
        // not
        // privileged users (root)
        try {
        	// echoServer = new ServerSocket(20908);
            echoServer = new ServerSocket(20208);
        } catch (IOException e) {
            System.out.println(e);
        }
        // Create a socket object from the ServerSocket to listen and
        // accept
        // connections.
        // Open input and output streams
        try {
            clientSocket = echoServer.accept();
            is = new DataInputStream(clientSocket.getInputStream());
            os = new PrintStream(clientSocket.getOutputStream());
            // As long as we receive data, echo that data back to the
            // client.
            while (true) {
                line = is.readLine();
                os.println("Echo: " + line);
            }
        } catch (IOException e) {
            System.out.println(e);
        }
    }    
    
}

Open in new window

0
Comment
Question by:habte
  • 9
  • 6
15 Comments
 
LVL 47

Expert Comment

by:for_yan
ID: 36544070


>Writing to socket and reading to socketchennel does seem to work.

WAht is it that you observe - is there some exception - or it is just waiting?

Also please elaborate - do you have them on one machine, or are you communicating across the network/

Such relatively long pieces of code is difficult to floow without additional information, unless
I cna run them myslef - how would I do it if I would like to try?
0
 

Author Comment

by:habte
ID: 36544579
hi Yan
here are the steps I take to run the socket server and client. Both the server-socket and client are running in same machine (pc)
1.      Run: GenericSocketServer
2.      Run: ConnectAsync
               a.      The issue is, when I run the client socket, I don’t see anything, it's just waiting., no output

if you want to run this, create this two classes on your IDE: eclipse. (make  sure you have live port ). In may case, the port number is “20208”, and see if you could see the issue. this is my first time using NIO.
the goal is to write to the socket channel and read from the socket channel. Only one socket
0
 
LVL 47

Expert Comment

by:for_yan
ID: 36544740

>make  sure you have live port - can you explain to me waht is a live port ?
I though I can use any number - no?
0
 

Author Comment

by:habte
ID: 36544819
sorry, live port is misleading, you can use any port.
0
 
LVL 47

Expert Comment

by:for_yan
ID: 36544840
OK, I'll try to do it and let you know
0
 

Author Comment

by:habte
ID: 36545414
ok,  thx
0
 
LVL 47

Expert Comment

by:for_yan
ID: 36545585
Well, good news is that it never waits with me

even when I run client first timwe after I start the server a\i get true ofr connection, so this is the oytput for the first time:

finishConnect(): true
check 2
request: 

Process finished with exit code 0

Open in new window


and it all happens very quickly

when I do it for the sceond time wiotyhout restarting the server
then it write false and a lot of doSomthing,
but that is the next story.

So tfisrt time it still does not return the string
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 47

Expert Comment

by:for_yan
ID: 36545669
Great!
I modified the server , and see waht I got on th server side (see output below):

import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class GenericSocketServer {


    public static void main(String args[]) {
        // declaration section:
        // declare a server socket and a client socket for the server
        // declare an input and an output stream
        ServerSocket echoServer = null;
        String line;
        DataInputStream is;
        PrintStream os;
        Socket clientSocket = null;
        // Try to open a server socket on port 9999
        // Note that we can't choose a port less than 1023 if we are
        // not
        // privileged users (root)
        try {
        	// echoServer = new ServerSocket(20908);
            echoServer = new ServerSocket(20208);
        } catch (IOException e) {
            System.out.println(e);
        }
        // Create a socket object from the ServerSocket to listen and
        // accept
        // connections.
        // Open input and output streams
        try {

            clientSocket = echoServer.accept();

            is = new DataInputStream(clientSocket.getInputStream());
            os = new PrintStream(clientSocket.getOutputStream());
            // As long as we receive data, echo that data back to the
            // client.
            while (true) {
                line = is.readLine();
                System.out.println(line);
                break;
             //   os.println("Echo: " + line);
            }
        } catch (IOException e) {
            System.out.println(e);
        }
    }

}

Open in new window


output:
New String to write to file...1316115885483

Process finished with exit code 0

Open in new window



So it at least receives something
0
 

Author Comment

by:habte
ID: 36545727
did you get anything "reading from a Socketchanne;"  it appears that it's writing to a socketchannel, but not able to read the data.
the output "request:" should include the following
request:New String to write to file...1316113948401
private static void readFromChannel(SocketChannel socketChannel )
    {
    	 Charset charset = Charset.forName("ISO-8859-1");

    	ByteBuffer buf = ByteBuffer.allocate(48);
    	CharsetDecoder decoder = charset.newDecoder();


    	try {
			int bytesRead = socketChannel.read(buf);
	          if (bytesRead == -1) {
	            //key.cancel();
	        	  System.out.println("bytesRead == -1 ");
	        	  socketChannel.close();
	           // continue;
	          }
	         buf.flip();
	          String request = decoder.decode(buf).toString();
	          System.out.println("request: " + request);
	          buf.clear();
	          

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

    }

Open in new window

0
 
LVL 47

Expert Comment

by:for_yan
ID: 36545849
No that part is not yet working
0
 
LVL 47

Expert Comment

by:for_yan
ID: 36546544
Sorry, could not make your code working - in the part of reading stuff back at the client

I found on internet much more complex code

http://rox-xmlrpc.sourceforge.net/niotut/

I downloaded all Java files (look at the bottom of this  page for full code)
and they were working - but it turned out that in their native form they are disconnected -
so this NioClient dioes not connect to this NioServer.

But when I changed one line in method main of the client
like that:
            //NioClient client = new NioClient(InetAddress.getByName("www.google.com"), 80);
            NioClient client = new NioClient(InetAddress.getByName("localhost"), 9090);

Then it does exactly as you wanted - it goes to the  server and server echoes back the result.

So it is much more complex - but for parctical reason - you can start from this code and use it and then modify it  - at least
it seems to be working fine - probably it is possuible to do it simpler..., but it at least works




0
 

Author Comment

by:habte
ID: 36561583
Still have same issue with “Nio Client”.
The print out is showing on the SocketServer side.
The read method “private void read(SelectionKey key)” is not reading the echo.
Tried to do the following
Added charsetDecoder and e.printStackTrace();  seed "read" method NoiClient
seems to get exception see log errors
thx

----------read method NioClient---------

private void read(SelectionKey key) throws IOException {
		SocketChannel socketChannel = (SocketChannel) key.channel();
		System.out.println("Check 0");
		 Charset charset = Charset.forName("ISO-8859-1");
	    	CharsetDecoder decoder = charset.newDecoder();
		// Clear out our read buffer so it's ready for new data
		this.readBuffer.clear();

		// Attempt to read off the channel
		int numRead;
		try {
			numRead = socketChannel.read(this.readBuffer);
		} catch (IOException e) {
			// The remote forcibly closed the connection, cancel
			// the selection key and close the channel.
			key.cancel();
			socketChannel.close();
			e.printStackTrace();
			return;
		}

		if (numRead == -1) {
			// Remote entity shut the socket down cleanly. Do the
			// same from our end and cancel the channel.
			System.out.println("numRead == -1");
			key.channel().close();
			key.cancel();
			return;
		}

		// Handle the response
		this.handleResponse(socketChannel, this.readBuffer.array(), numRead);
	}
------ errors below---------


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:25)
	at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:237)
	at sun.nio.ch.IOUtil.read(IOUtil.java:210)
	at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:236)
	at com.lmco.isgs.test.nio.bk.NioClient.read(NioClient.java:124)
	at com.lmco.isgs.test.nio.bk.NioClient.run(NioClient.java:102)
	at java.lang.Thread.run(Thread.java:662)

Open in new window

0
 
LVL 47

Expert Comment

by:for_yan
ID: 36561794

Sorry, do you mean that you are   now relying on the code from http://rox-xmlrpc.sourceforge.net/niotut/
or form your old code?

I see code from http://rox-xmlrpc.sourceforge.net/niotut/

If you are trying to use it - I would first compile everything as it is and make sure it works like
it worked for me.

After that already the changes can be made
0
 

Author Comment

by:habte
ID: 36562312
OK, i see, it seem to work with NioServer. however, could you get it to work with "GenericSocketServer"? that's what i was referring on the earlier comment.
thx
0
 
LVL 47

Accepted Solution

by:
for_yan earned 500 total points
ID: 36562371
Well, maybe, but it probably will require some work.

If you need some specific funxctionatlity why would not you try to modify their code
to accommodate what you need?

Well, on the one side it is not so easy to modify other people's code,
ebven though taht guy seesm to have written a pretty good explanaton.
On the other hand when you do something new, it is easier to start with something which
at least has general functionality working and then moddify it cautiously
making sure that you are not breaking it, then to start fro something which does not work
and overcome the first big hurdle to make it work.
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

By the end of 1980s, object oriented programming using languages like C++, Simula69 and ObjectPascal gained momentum. It looked like programmers finally found the perfect language. C++ successfully combined the object oriented principles of Simula w…
This was posted to the Netbeans forum a Feb, 2010 and I also sent it to Verisign. Who didn't help much in my struggles to get my application signed. ------------------------- Start The idea here is to target your cell phones with the correct…
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now