java nio socket客户端和服务器端的实现,nio socket是java.nio包下的socket,它比java.net下的socket更加高效,是一种非阻塞式的socket,采用Selector选择器形式来选择空闲的channel通道执行,Selector如我们银行叫号机器,整个项目只有一个selector叫号器,channel通道一旦建立,只要客户端不退出,就一直保持长连接的形式,如图所示。

1:下面来通过案例让我们理解nio socket的使用方法,先来看看socket server服务器端的写法,代码如下。
package com.baidu;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
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.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class NioSocketServer {
private Selector selector;
private InetSocketAddress socketAddress;
private Map<SocketChannel,List> channelMap;
//构造方法
public NioSocketServer(String address,int port){
socketAddress = new InetSocketAddress(address, port);
channelMap = new HashMap<SocketChannel,List>();
}
public static void main(String[] args) {
Runnable server = new Runnable() {
@Override
public void run() {
try {
new NioSocketServer("localhost", 8888).startServer();
} catch (IOException e) {
e.printStackTrace();
}
}
};
//启动线程
new Thread(server).start();
}
//创建服务器channel通道
protected void startServer() throws IOException {
//Selector对象是通过调用静态工厂方法open()来实例化
selector = Selector.open();
ServerSocketChannel serverChannel = ServerSocketChannel.open();
//非阻塞
serverChannel.configureBlocking(false);
serverChannel.socket().bind(socketAddress);
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("服务器启动了.........");
//一直处于循环状态,便于处理客户端信息
while(true){
//等待客户端的事件
selector.select();
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while(keys.hasNext()){
SelectionKey key = keys.next();
//防止相同的操作
keys.remove();
//无效则不进行下面操作
if (!key.isValid()) {
continue;
}
//如果是客户端连接操作
if (key.isAcceptable()) {
acceptConnection(key);
}
//如果是客户端来的信息,则读出来
if (key.isReadable()) {
readMessage(key);
}
}
}
}
//客户端连接操作
private void acceptConnection(SelectionKey key) throws IOException {
ServerSocketChannel serverChannel = (ServerSocketChannel)key.channel();
SocketChannel channel = serverChannel.accept();
channel.configureBlocking(false);
Socket socket = channel.socket();
SocketAddress remoteAddress = socket.getRemoteSocketAddress();
System.out.println("连接的客户端ip是:"+remoteAddress);
//开启读取数据
channelMap.put(channel, new ArrayList<>());
channel.register(selector, SelectionKey.OP_READ);
}
//读取客户端信息
private void readMessage(SelectionKey key) throws IOException {
SocketChannel channel = (SocketChannel)key.channel();
try {
//nio的字节缓存大小
ByteBuffer buffer = ByteBuffer.allocate(1024);
int num = -1;
num = channel.read(buffer);
//如果数据读取完毕
if (num == -1) {
channelMap.remove(channel);
Socket socket = channel.socket();
SocketAddress remoteAddress = socket.getRemoteSocketAddress();
System.out.println("退出的客户端ip是:"+remoteAddress);
channel.close();
key.cancel();
}
byte[] datas = new byte[num];
System.arraycopy(buffer.array(), 0, datas, 0, num);
String msg = new String(datas);
System.out.println("服务端读取到的数据:"+msg);
} catch (Exception e) {
//客户端异常退出,则关闭通道,不影响服务端socket
channelMap.remove(channel);
Socket socket = channel.socket();
SocketAddress remoteAddress = socket.getRemoteSocketAddress();
System.out.println("退出的客户端ip是:"+remoteAddress);
channel.close();
key.cancel();
}
}
}2:nio client客户端代码,启动连接服务器端。
package com.baidu;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Scanner;
public class NioSocketClient {
public static void main(String[] args) throws IOException {
InetSocketAddress socketAddress = new InetSocketAddress("localhost", 8888);
SocketChannel client = SocketChannel.open(socketAddress);
while(true){
//获取键盘录入
Scanner scanner = new Scanner(System.in);
System.out.println("我说:");
String message = scanner.nextLine();
ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());
client.write(buffer);
}
}
}学会nio socket非常的重要,因为它是netty框架的基础,对于以后了解netty socket非常的有用。