Java NIO 之 ServerSocketChannel 与 SocketChannel

  • ServerSocketChannel

  • ServerSocketChannel作用?就是专职干什么的?

1、监听新进来的TCP链接通道,

2、创建新的SocketChannel

  • ServerSocketChannel 不具备 什么能力

ServerSocketChannel并不能进行数据传输的能力

  • 如何创建ServerSocketChannel实例

ServerSocketChannel socketChannel =ServerSocketChannel.open();

该对象关联了一个未绑定ServerSocket的通道,

  • 为ServerSocketChannel绑定监听端口号

JDK1.7前,需要调用ServerSocketChannel的socket方法,再调用bind()来进行关联

JDK1.7后,就可以直接调用ServerSocketChannel的bind()来进行端口绑定了。

  • ServerSocketChannel如何监听新进来的连接

通过 ServerSocketChannel.accept() 方法监听新进来的连接。

ServerSocketChannel 默认是 阻塞模式,可以查看JDK源码

如下,所示:

通过ServerSocketChannel.configureBlocking(true)来设定阻塞模式

1、在阻塞模式下,

如果有新的连接进来,那么accept()方法返回的是一个包含新进来的连接的SocketChannel,

如果没有新的连接,那么accept()方法,就会一直阻塞在这里,直到有的新连接进来

2、在非阻塞模式下ServerSocketChannel. configureBlocking(false)

如果有连接进来,那么accept()方法返回的是一个包含新进来的连接的SocketChannel

如果没有新的连接,那么accept()方法会立即返回null

3、阻塞模式与非阻塞模式的根本区别?

其实,就是在没有新的连接的情况下,如何处理的?不返回,一直等待的话,就是阻塞;

如果立即返回的话,就是非阻塞了。

  • SocketChannel

  • 创建SocketChannel的方式?

方式一:在客户端创建

SocketChannel socketChannel = SocketChannel.open();

方式二:在服务器端创建

ServerSocketChannel接受一个连接请求后得到,如

SocketChannel socketChannel = serverSocketChannel.accept();

  • 将管道中的数据读到缓存里,用的是socketChannel的read方法

int read = socketChannel.read(sizeBuffer);

  • 将缓存里的数据写到管道中,用的是socketChannel的write方法

socketChannel.write(sizeBuffer);

例子如下:

服务端:

package xingej.channel;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

public class ServerSocketChannelTest {
    public void initChannel() throws IOException {
        //服务器端,通过open方法,来创建ServerSocketChannel
        //注意,此时,服务器端,还没有进行绑定端口呢
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

        //设置为非阻塞模式
//        serverSocketChannel.configureBlocking(false);
        //绑定端口号
        //JDK1.7版本之后的写法
        serverSocketChannel.bind(new InetSocketAddress(8081));
        //JDK1.7版本之前的写法
//        serverSocketChannel.socket().bind(new InetSocketAddress(8081));

        //创建字节缓存区
        //缓存区的大小是1024字节,这个可以自己调试,如改成64,128....
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

        while (true) {
            System.out.println("-------服务器端-----开始接收-----客户端的连接---------");
            //在服务器端,接收客户端的链接,如果存在客户端的话,就返回一个
            //SocketChannel对象
            //如果是阻塞模式的话,没有新的链接进来,就会阻塞在这里,否则,往下执行
            //如果是非阻塞模式的话,没有新的链接进来,就会立马返回一个null,程序不会阻塞在这里,
            //会立马往下进行的
            SocketChannel socketChannel = serverSocketChannel.accept();
            if (null != socketChannel) {
                while (true) {
                    //清楚缓存区的数据,可以接收新的数据
                    byteBuffer.clear();

                    //将管道socketChannel的数据读取到 缓存byteBuffer里
                    //readSize 表示 读取的字节数
                    int readSize = socketChannel.read(byteBuffer);
                    if (readSize == -1) {
                        break;
                    }
                    //再从 字节缓存里,进行其他 业务逻辑操作,                    // 注意,这里的缓存区使用的字节类型
                    // 因此,如果需要其他类型的话,需要进行转换
                    System.out.println(new String(byteBuffer.array()));
                }
            }

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws IOException {
        new ServerSocketChannelTest().initChannel();
    }
}

客户端如下:

package xingej.channel;

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

public class SocketChannelTest {

    public void connectServer() throws IOException{
        // 创建一个 SocketChannel对象,
        // 请注意,并没有进行 链接服务器端哦
        SocketChannel socketChannel = SocketChannel.open();

        //开始链接服务器端
        socketChannel.connect(new InetSocketAddress("localhost", 8081));

        //在客户端创建 字节缓存区
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

        String msg = "\nhello, nio, hello ,spark, hello ,hadoop, flume, mesos, marathon, netty, mina, stream, inputstream, outputstream \n" +
                "hello, nio, hello ,spark, hello ,hadoop, flume, mesos, marathon, netty, mina, stream, inputstream, outputstream \n" +
                "hello, nio, hello ,spark, hello ,hadoop, flume, mesos, marathon, netty, mina, stream, inputstream, outputstream 北京\n";

        //往字节缓存区,添加数据
        byteBuffer.put(msg.getBytes());
        // 针对是更新limit值,将此值更新为position了,用于接下来的读操作
        byteBuffer.flip();
        while(byteBuffer.hasRemaining()) {
            //将字节缓存里的数据,写到管道中去
            socketChannel.write(byteBuffer);
        }

        socketChannel.close();
    }

    public static void main(String[] args) throws IOException{
        new SocketChannelTest().connectServer();
    }
}

启动方式:

先启动服务器端,然后再启动客户端

时间: 2024-08-30 11:27:14

Java NIO 之 ServerSocketChannel 与 SocketChannel的相关文章

Java NIO (9) ServerSocketChannel

Java NIO ServerSocketChannel A Java NIO ServerSocketChannel is a channel that can listen for incoming TCP connections, just like a ServerSocket in standard Java Networking. The ServerSocketChannel class is located in the java.nio.channelspackage. Her

JAVA NIO ServerSocketChannel(线程池版)

服务器端: import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSock

【JAVA】【NIO】10、Java NIO ServerSocketChannel

Java NIO的ServerSocketChannel是用来监听外来TCP连接的channel,就想标准Java网络中的ServerSocket.实例如下: ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.socket().bind(new InetSocketAddress(8090)); while(true) { SocketChannel socketCh

Java NIO示例:多人网络聊天室

一个多客户端聊天室,支持多客户端聊天,有如下功能: 功能1: 客户端通过Java NIO连接到服务端,支持多客户端的连接 功能2:客户端初次连接时,服务端提示输入昵称,如果昵称已经有人使用,提示重新输入,如果昵称唯一,则登录成功,之后发送消息都需要按照规定格式带着昵称发送消息 功能3:客户端登录后,发送已经设置好的欢迎信息和在线人数给客户端,并且通知其他客户端该客户端上线 功能4:服务器收到已登录客户端输入内容,转发至其他登录客户端. 功能5 TODO:客户端下线检测  方案是:客户端在线的时候

基于Java NIO的Socket通信

Java NIO模式的Socket通信,是一种同步非阻塞IO设计模式,它为Reactor模式实现提供了基础. 下面看看,Java实现的一个服务端和客户端通信的例子. NIO模式的基本原理描述如下: 服务端打开一个通道(ServerSocketChannel),并向通道中注册一个选择器(Selector),这个选择器是与一些感兴趣的操作的标识(SelectionKey,即通过这个标识可以定位到具体的操作,从而进行响应的处理)相关联的,然后基于选择器(Selector)轮询通道(ServerSock

Java NIO原理 图文分析及代码实现

Java NIO原理 图文分析及代码实现 博客分类: java底层 java NIO原理阻塞I/O非阻塞I/O Java NIO原理图文分析及代码实现 前言:  最近在分析hadoop的RPC(Remote Procedure Call Protocol ,远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.可以参考:http://baike.baidu.com/view/32726.htm )机制时,发现hadoop的RPC机制的实现主要用到了两个技术

JAVA NIO 服务器与客户端实现示例

以下代码只兼容Java 7及以上版本,对于一些关键地方请看注释说明. 公共类: package com.stevex.app.nio; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; imp

[JavaEE]Java NIO原理图文分析及代码实现

转http://weixiaolu.iteye.com/blog/1479656 目录: 一.java NIO 和阻塞I/O的区别      1. 阻塞I/O通信模型      2. java NIO原理及通信模型 二.java NIO服务端和客户端代码实现 具体分析: 一.java NIO 和阻塞I/O的区别 1. 阻塞I/O通信模型 假如现在你对阻塞I/O已有了一定了解,我们知道阻塞I/O在调用InputStream.read()方法时是阻塞的,它会一直等到数据到来时(或超 时)才会返回:同

Java NIO的探究

1.Java NIO与阻塞IO的区别 阻塞IO通信模型(在上一篇<J2SE网络编程之 TCP与UDP>博客中有所介绍) 我们知道阻塞I/O在调用InputStream.read()方法时是阻塞的,它会一直等到数据到来时(或超时)才会返回:同样,在调用ServerSocket.accept()方法时,也会一直阻塞到有客户端连接才会返回,每个客户端连接过来后,服务端都会启动一个线程去处理该客户端的请求.阻塞I/O的通信模型示意图如下: 如果你细细分析,一定会发现阻塞I/O存在一些缺点.根据阻塞I/