Channel是nio包的一个抽象类,作为java nio的三大组件(Buffer、Channel,Selector)之一,在java nio网络编程中尤为重要。
Channel是读写数据的双向通道,可以从Channel将数据读取Buffer,也可将Buffer的数据写入Channel。我们这里主要讨论用于网络编程的ServerSocketChannel,SocketChannel,DatagramChannel。
本文档需要使用Buffer操作,Buffer的使用可参考:http://t.csdn.cn/f1ZB9。
2、代码演示(阻塞)服务端
public class Server {
public static void main(String[] args) throws IOException {
//创建服务端Channel
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//服务端channel监听8080端口
serverSocketChannel.bind(new InetSocketAddress(8080));
while (true){
//阻塞等待tcp客户端连接
SocketChannel channel = serverSocketChannel.accept();
InetSocketAddress remoteAddress = (InetSocketAddress) channel.getRemoteAddress();
System.out.println("客户端信息:"+remoteAddress.getAddress().getHostAddress()+" "+remoteAddress.getPort());
//处理客户端channel消息读写操作
handleMsg(channel);
}
}
public static void handleMsg(SocketChannel channel){
new Thread(()->{
//创建大小为100的字节缓冲区,用于配合Channel读写操作
ByteBuffer buffer = ByteBuffer.allocate(100);
try {
while (true){
//阻塞等待接收已连接的tcp客户端数据
int readCount = channel.read(buffer);
if(readCount<=0){
channel.close();
break;
}
//limit = position;position = 0;
buffer.flip();
//mark = position;(记录position位置)
buffer.mark();
System.out.println("接收到字节数据:");
while (buffer.position()
System.out.print(buffer.get()+" ");
}
System.out.println();
//position = mark;(将记录的position位置恢复)
buffer.reset();
//向tcp客户端写数据
channel.write(buffer);
buffer.clear();
}
} catch (Exception e) {
e.printStackTrace();
}finally {
closeIO(channel);
}
}).start();
}
//关闭流方法
private static void closeIO(Closeable io){
if(io!=null){
try{
io.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
客户端
public class Client {
public static void main(String[] args) throws IOException {
//创建客户端Channel
SocketChannel channel = SocketChannel.open();
//指定服务端ip、port进行连接
channel.connect(new InetSocketAddress("127.0.0.1",8080));
//接收服务端写入数据
handleMsg(channel);
Scanner scanner = new Scanner(System.in);
while (true){
String str = scanner.next();
if("exit".equals(str)){
break;
}
ByteBuffer buffer = ByteBuffer.wrap(str.getBytes());
channel.write(buffer);
}
closeIO(channel);
}
public static void handleMsg(SocketChannel channel) {
new Thread(()->{
//创建大小为100的字节缓冲区,用于配合Channel读写操作
ByteBuffer buffer = ByteBuffer.allocate(100);
try {
while (true){
//阻塞等待接收tcp服务端数据
int readCount = channel.read(buffer);
if(readCount<=0){
channel.close();
break;
}
//limit = position;position = 0;
buffer.flip();
System.out.println("接收到数据:");
while (buffer.position()
System.out.print(buffer.get()+" ");
}
System.out.println();
//position = 0;limit = capacity;mark = -1;
buffer.clear();
}
}catch (Exception e){
e.printStackTrace();
}finally {
closeIO(channel);
}
}).start();
}
//关闭流方法
private static void closeIO(Closeable io){
if(io!=null){
try{
io.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
3、Channel非阻塞操作
ServerSocketChannel(部分代码)
//创建服务端Channel ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); //服务端channel监听8080端口 serverSocketChannel.bind(new InetSocketAddress(8080)); //将ServerSocketChannel设置为非阻塞模式 serverSocketChannel.configureBlocking(false); SocketChannel channel = serverSocketChannel.accept();
SocketChannel(部分代码)
//创建客户端Channel
SocketChannel channel = SocketChannel.open();
//指定服务端ip、port进行连接
channel.connect(new InetSocketAddress("127.0.0.1",8080));
//创建大小为100的字节缓冲区,用于配合Channel读写操作
ByteBuffer buffer = ByteBuffer.allocate(100);
channel.configureBlocking(false);
int readCount = channel.read(buffer);
暑期编程PK赛
得CSDN机械键盘等精美礼品!


