Updated February 6, 2023
Introduction to Java NIO SocketChannel
A java NIO Socketchannel is mainly attached to a TCP network socket, so it serves as a java networking’s sockets that is related and equivalent to java nio. It has two different ways to implement this in NIO, open the SocketChannel and the same will be connected and mapped to the server end which is on the cloud internet and also it will be created if we receive the incoming connections that arrives at the ServerSocketChannel.
Key Takeaways
- It is used to connect sockets for data stream-oriented on data flow channels.
- Using open(), connect(), isConnected(), finishConnect() are some of the methods used for performing the socket operations.
- Each data connection is referred as channel.
- It supports concurrent reading and writing operation thread.
- Connect and finishConnect() methods are mutually synchronized each other.
What is Java NIO SocketChannel?
There are two different ways to implement this in NIO: open the SocketChannel and it will be connected and mapped to the server end that is on the cloud internet. It will also be created if we receive the incoming connections that arrive at the ServerSocketChannel. A Java NIO Socketchannel is primarily attached to a TCP network socket, so it serves as a java networking’s socket that is related and equivalent to Java NIO.
Opening and Closing a SocketChannel
The java nio Socketchannel is mainly used to connect the channel sockets for data stream-oriented along with data flow that selectable through via same channel type. Its meaning is same can be on multiplexed channel using a selector if it’s there not been already called an open socket using the static open() method. Socketchannel will create one separately while calling the open() method but before connecting a Socketchannel its to be formed. Calling the connect() method will establish through a Socketchannel connection. The same thing will help to note that on the data channel, to throw a NotYetConnectedException if any I/O activity is attempted while its not connected. Therefore before doing the Input and Output operations we should confirm first whether that specific channel is connected or not. Once a channel is opened it should stay open until its closed. By calling its isConnected method whether the state of the specific Socketchannel can be discovered.
If we use Socketchannel’s finishConnect() method, the connection can be closed. isConnectionPending method can be used to check whether a specific connection activity is active or not and Non-blocking connections are mainly supported by the Socketchannels by its default. Moreover, additionally its supported an asynchronous shutdown technique and feature that has been more comparable to the close method which is on the channel class. Its safe to use on multiple concurrent threads by using Socketchannels and they allowed for simultaneous reading and writing techniques at the specified time. Since the connect and finishConnect methods are mutually synchronized and attempting to start a read and write operation methods. Its being invoked and it cause a transaction block until the specific invocation is completed.
Java NIO SocketChannel Methods
- bind(SocketAddress variable): This method helps to bind the Socketchannel to the local address that is supplied as the parameter arguments.
- connect(SocketAddress remote): By using this method whether the socket is connected to the remote address with help of procedure connect.
- finishConnect(): During this method whether it completes the connection of a Socketchannel.
- getRemoteAddress(): The address of the remote site is to which whether the channel’s socket is linked and returned by the getRemoteAddress() method.
- isConnected(): It returns the connection state of the Socketchannel whether it will be connected or not.
- open() and open((SocketAddress remote): These methods are used to open a web Socketchannel with no address specification and supplied while the parameterized open method. It opens the channel with a remote address and established the data connection. This handy technique will behave though were open() method with Socketchannel connection. And passing the remote connection and returning the data channel.
- read(ByteBuffer byts): In this method it helps to read data from a buffer across the web Socketchannel.
- isConnectionPending(): It indicates whether or not a connection between the transaction and its currently placing on the same channel.
SocketChannel – Non-blocking Mode (I/O)
It entails that the function is instantly and returned after the user request has been queued. Then at a later stage the real I/O is processed and it can effectively queried a socket by switching it to a non-blocking mode. It’s another choice that may be available for unique distinction in its name and other operation with carried out blocking. Non-blocking Input and Output choices are easily entered at the function level after receiving the user request on queued. We can effectively process the query on web socket by switching it to a non-blocking mode and it returned the error code. It also helps to read the data from a non-blocking socket when there is no data.
Polling readiness is one of the mechanism with query approach for each socket readiness and one its not prepared for the new I/O activity. We can also perform these operations in the queue once with sockets prepared after it goes back to the blocking state and wait sockets prepared and subsequent I/O operation.
Example:
Client:
package TestNG;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Iterator;
import java.util.Set;
public class nonio {
static BufferedReader uinps = null;
public static boolean second(@SuppressWarnings("rawtypes") Set sets) throws Exception {
@SuppressWarnings("rawtypes")
Iterator itr = sets.iterator();
while (itr.hasNext()) {
SelectionKey skeys = (SelectionKey)
itr.next();
itr.remove();
if (skeys.isConnectable()) {
boolean clientconnect = first(skeys);
if (!clientconnect) {
return true;
}
}
if (skeys.isReadable()) {
String str = finals(skeys);
System.out.println("Server read the keys " + str);
}
if (skeys.isWritable()) {
System.out.print("Please enter your inputs");
String str1 = uinps.readLine();
if (str1.equalsIgnoreCase("Thanks again try")) {
return true;
}
SocketChannel chnel = (SocketChannel) skeys.channel();
ByteBuffer buf = ByteBuffer.wrap(str1.getBytes());
chnel.write(buf);
}
}
return false;
}
public static boolean first(SelectionKey sky) throws Exception{
SocketChannel chn = (SocketChannel) sky.channel();
while (chn.isConnectionPending()) {
chn.finishConnect();
}
return true;
}
public static String finals(SelectionKey skys) throws Exception {
SocketChannel chnsl = (SocketChannel) skys.channel();
ByteBuffer bufs = ByteBuffer.allocate(1024);
chnsl.read(bufs);
bufs.flip();
Charset chset = Charset.forName("UTF-8");
CharsetDecoder decs = chset.newDecoder();
CharBuffer chbuf = decs.decode(bufs);
String msgg = chbuf.toString();
return msgg;
}
public static void main(String[] args) throws Exception {
InetAddress ip = InetAddress.getByName("localhost");
int prt = 19000;
InetSocketAddress sddr = new InetSocketAddress(
ip, prt);
Selector slc = Selector.open();
SocketChannel chnels = SocketChannel.open();
chnels.configureBlocking(false);
chnels.connect(sddr);
int ops = SelectionKey.OP_CONNECT | SelectionKey.OP_READ
| SelectionKey.OP_WRITE;
chnels.register(slc, ops);
uinps = new BufferedReader(new InputStreamReader(System.in));
while (true) {
if (slc.select() > 0) {
boolean ress = second(slc.selectedKeys());
if (ress) {
break;
}
}
}
chnels.close();
}
}
Server:
package TestNG;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
public class nioserver {
public static void main(String[] args) throws Exception {
InetAddress hip = InetAddress.getByName("localhost");
int prt = 19000;
Selector slc = Selector.open();
ServerSocketChannel schnl = ServerSocketChannel.open();
schnl.configureBlocking(false);
schnl.socket().bind(new InetSocketAddress(hip, prt));
schnl.register(slc, SelectionKey.OP_ACCEPT);
while (true) {
if (slc.select() <= 0) {
continue;
}
first(slc.selectedKeys());
}
}
public static void first(Set sets) throws Exception {
Iterator itr = sets.iterator();
while (itr.hasNext()) {
SelectionKey kys = (SelectionKey) itr.next();
itr.remove();
if (kys.isAcceptable()) {
ServerSocketChannel schnls = (ServerSocketChannel) kys.channel();
SocketChannel chnlss = (SocketChannel) schnls.accept();
chnlss.configureBlocking(false);
chnlss.register(kys.selector(), SelectionKey.OP_READ);
}
if (kys.isReadable()) {
String msgs = second(kys);
if (msgs.length() > 0) {
SocketChannel schnlsss = (SocketChannel) kys.channel();
ByteBuffer buf = ByteBuffer.wrap(msgs.getBytes());
schnlsss.write(buf);
}
}
}
}
public static String second(SelectionKey ky1) throws Exception {
SocketChannel chnels = (SocketChannel) ky1.channel();
ByteBuffer bufs = ByteBuffer.allocate(1024);
int bconunt = chnels.read(bufs);
if (bconunt > 0) {
bufs.flip();
return new String(bufs.array());
}
return "Welcome";
}
}
Output:
- Above example I have created nio client and server programs.
- Additionally, I have called the Java File classes and its methods.
- Created separate socket client and server instances and called the required methods.
- Through the help of Socketchannels the keys are triggered and send the user inputs to the server.
- Finally, it return the outputs on buffer format and the same will be printed on the console.
Java NIO SocketChannel to Writing
The data writing is connected to a Socketchannel which is mainly done through via the Socketchannel. Mainly the resource should allocate as the data buffer in parameter while entered as the write() method. Because the number of bytes we can use write() method to publish the SocketChannel. Its very unknown and utilised the SocketChannel.write() method with inside of a while-loop iteration. And it will repeat the same write() method until there are no more bytes to be written on the buffer storage.
Example:
SocketClient:
package TestNG;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.EnumSet;
public class socketclient {
public static void main(String[] args) throws IOException {
ServerSocketChannel schannel = null;
SocketChannel sc = null;
schannel = ServerSocketChannel.open();
schannel.socket().bind(new InetSocketAddress(9000));
sc = schannel.accept();
System.out.println("We need to set the connection " + sc.getRemoteAddress());
Path pth = Paths.get("E://first.txt");
FileChannel fchannel = FileChannel.open(pth,
EnumSet.of(StandardOpenOption.CREATE,
StandardOpenOption.TRUNCATE_EXISTING,
StandardOpenOption.WRITE)
);
ByteBuffer buf = ByteBuffer.allocate(1024);
while(sc.read(buf) > 0) {
buf.flip();
fchannel.write(buf);
buf.clear();
}
fchannel.close();
System.out.println("We received the File");
sc.close();
}
}
SocketServer:
package TestNG;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.EnumSet;
public class socketclient {
public static void main(String[] args) throws IOException {
ServerSocketChannel schannel = null;
SocketChannel sc = null;
schannel = ServerSocketChannel.open();
schannel.socket().bind(new InetSocketAddress(9000));
sc = schannel.accept();
System.out.println("We need to set the connection " + sc.getRemoteAddress());
Path pth = Paths.get("E://first.txt");
FileChannel fchannel = FileChannel.open(pth,
EnumSet.of(StandardOpenOption.CREATE,
StandardOpenOption.TRUNCATE_EXISTING,
StandardOpenOption.WRITE)
);
ByteBuffer buf = ByteBuffer.allocate(1024);
while(sc.read(buf) > 0) {
buf.flip();
fchannel.write(buf);
buf.clear();
}
fchannel.close();
System.out.println("We received the File");
sc.close();
}
}
Output:
- In the above example we used socket connection between the client and server.
- Used default import java classes and its methods.
- Additionally I/O operations, File Creation and its methods.
- For each looping once the connection is opened and performed the operation then its closed using close() method.
- While loop is used to iterate the values based on the buffer conditions.
Conclusion
Here we covered the basic usage of NIO selector components and its channels. The client and server Socketchannels are covered and performed the thread operation for sending and receiving the messages including file attachment. Each datas are connected through via channel and the test execution is completed once the Socketchannel is closed.
Recommended Articles
This is a guide to Java NIO SocketChannel. Here we discuss the introduction, methods, opening and closing a SocketChannel, and non-blocking mode (I/O). You can also look at the following articles to learn more –