JAVA-NIO之Socket/ServerSocket Channel(详解)

一、ServerSocketChannel

Java NIO中的 ServerSocketChannel 是一个可以监听新进来的TCP连接的通道, 就像标准IO中的ServerSocket一样。ServerSocketChannel类在 java.nio.channels包中。

打开 ServerSocketChannel

通过调用 ServerSocketChannel.open() 方法来打开ServerSocketChannel.

关闭 ServerSocketChannel

通过调用ServerSocketChannel.close() 方法来关闭ServerSocketChannel.

监听新进来的连接

通过 ServerSocketChannel.accept() 方法监听新进来的连接。当 accept()方法返回的时候,它返回一个包含新进来的连接的 SocketChannel。因此, accept()方法会一直阻塞到有新连接到达。

通常不会仅仅只监听一个连接,在while循环中调用 accept()方法.

当然,也可以在while循环中使用除了true以外的其它退出准则。

非阻塞模式

ServerSocketChannel可以设置成非阻塞模式。在非阻塞模式下,accept() 方法会立刻返回,如果还没有新进来的连接,返回的将是null。 因此,需要检查返回的SocketChannel是否是null.如:

/**
   * socket server channel
   */
  @Test
  public void text2() throws IOException {
    ServerSocketChannel channel = ServerSocketChannel.open();  //新建channel
    channel.socket().bind(new InetSocketAddress(9999));   //监听端口
    channel.configureBlocking(true);               //设置阻塞

    while (true) {
      SocketChannel accept = channel.accept();          //设置为阻塞,则此方法阻塞,直到有连接
      //如果设置为非阻塞,需要在这里判断 accept == null?
      ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
      accept.read(byteBuffer);
      byteBuffer.flip();                  //反转
      while (byteBuffer.hasRemaining()) {          //判断
        System.err.println((char)byteBuffer.get());    //输出
      }
    }
  }

二、SocketChannel

Java NIO中的SocketChannel是一个连接到TCP网络套接字的通道。可以通过以下2种方式创建SocketChannel:

打开一个SocketChannel并连接到互联网上的某台服务器。

一个新连接到达ServerSocketChannel时,会创建一个SocketChannel。

打开 SocketChannel

下面是SocketChannel的打开方式:

关闭 SocketChannel

当用完SocketChannel之后调用SocketChannel.close()关闭SocketChannel:

从 SocketChannel 读取数据

要从SocketChannel中读取数据,调用一个read()的方法之一。

首先,分配一个Buffer。从SocketChannel读取到的数据将会放到这个Buffer中。

然后,调用SocketChannel.read()。该方法将数据从SocketChannel 读到Buffer中。read()方法返回的int值表示读了多少字节进Buffer里。如果返回的是-1,表示已经读到了流的末尾(连接关闭了)。

写入 SocketChannel

写数据到SocketChannel用的是SocketChannel.write()方法,该方法以一个Buffer作为参数。

注意SocketChannel.write()方法的调用是在一个while循环中的。Write()方法无法保证能写多少字节到SocketChannel。所以,我们重复调用write()直到Buffer没有要写的字节为止。

非阻塞模式

可以设置 SocketChannel 为非阻塞模式(non-blocking mode).设置之后,就可以在异步模式下调用connect(), read() 和write()了。

connect()

如果SocketChannel在非阻塞模式下,此时调用connect(),该方法可能在连接建立之前就返回了。为了确定连接是否建立,可以调用finishConnect()的方法。

write()

非阻塞模式下,write()方法在尚未写出任何内容时可能就返回了。所以需要在循环中调用write()。前面已经有例子了,这里就不赘述了。

read()

非阻塞模式下,read()方法在尚未读取到任何数据时可能就返回了。所以需要关注它的int返回值,它会告诉你读取了多少字节。

非阻塞模式与选择器

非阻塞模式与选择器搭配会工作的更好,通过将一或多个SocketChannel注册到Selector,可以询问选择器哪个通道已经准备好了读取,写入等。Selector与SocketChannel的搭配使用会在后面详讲。

/**
   * socket channel
   */
  @Test
  public void test3() throws IOException {
    SocketChannel channel = SocketChannel.open();                //新建服务端
    channel.connect(new InetSocketAddress("127.0.0.1",9999));  //连接服务端地址
    ByteBuffer byteBuffer = ByteBuffer.allocate(1024); //缓冲区
    byteBuffer.put("123".getBytes());
    byteBuffer.flip();                 //反转
    while (byteBuffer.hasRemaining()) {         //判断
      channel.write(byteBuffer);
    }
  }

以上这篇JAVA-NIO之Socket/ServerSocket Channel(详解)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Java Socket编程实例(四)- NIO TCP实践

    一.回传协议接口和TCP方式实现: 1.接口: import java.nio.channels.SelectionKey; import java.io.IOException; public interface EchoProtocol { void handleAccept(SelectionKey key) throws IOException; void handleRead(SelectionKey key) throws IOException; void handleWrite(

  • Java Socket编程实例(五)- NIO UDP实践

    一.回传协议接口和UDP方式实现: 1.接口: import java.nio.channels.SelectionKey; import java.io.IOException; public interface EchoProtocol { void handleAccept(SelectionKey key) throws IOException; void handleRead(SelectionKey key) throws IOException; void handleWrite(

  • JAVA-NIO之Socket/ServerSocket Channel(详解)

    一.ServerSocketChannel Java NIO中的 ServerSocketChannel 是一个可以监听新进来的TCP连接的通道, 就像标准IO中的ServerSocket一样.ServerSocketChannel类在 java.nio.channels包中. 打开 ServerSocketChannel 通过调用 ServerSocketChannel.open() 方法来打开ServerSocketChannel. 关闭 ServerSocketChannel 通过调用Se

  • Java 网络编程socket编程等详解

    网络编程是指编写运行在多个设备(计算机)的程序,这些设备都通过网络连接起来. java.net包中J2SE的API包含有类和接口,它们提供低层次的通信细节.你可以直接使用这些类和接口,来专注于解决问题,而不用关注通信细节. java.net包中提供了两种常见的网络协议的支持: TCP: TCP是传输控制协议的缩写,它保障了两个应用程序之间的可靠通信.通常用于互联网协议,被称TCP / IP. UDP:UDP是用户数据报协议的缩写,一个无连接的协议.提供了应用程序之间要发送的数据的数据包. 本教程

  • Java使用Socket简单通讯详解

    目录 Java实现基于Socket的简单通信  一.ServerSocket 1.使用JavaFX写的小界面,方便观察客户端连接情况 2.创建ServerSocket并处理客户端连接并显示客户端基本信息 3.新建Handle类处理接收发送两个客户端的消息 二.Socket 1.同样的编写一个客户端界面 2.创建Socket连接客户端并获取输入输出流 3.添加编辑框监听处理消息发送 4.创建新线程从服务器上接收消息 三.测试 四.总结 1.原理流程 2.不足之处 Java实现基于Socket的简单

  • Java使用TCP实现数据传输实例详解

    Java使用TCP实现数据传输实例详解 TCP所提供服务的主要特点: 1.面向连接的传输: 2.端到端的通信: 3.高可靠性,确保传输数据的正确性,不出现丢失或乱序: 4.全双工方式传输: 5.采用字节流方式,即以字节为单位传输字节序列: 6.紧急数据传送功能. TCP传输需要建立客户端和服务器端,即Socket和Server Socket , 建立连接后,通过Socket中的IO流进行数据的传输 .传输结束后关闭Socket. 客户端和服务器端是两个独立的应用程序. 以下是实现基本的TCP数据

  • Java编程实现排他锁代码详解

    一 .前言 某年某月某天,同事说需要一个文件排他锁功能,需求如下: (1)写操作是排他属性 (2)适用于同一进程的多线程/也适用于多进程的排他操作 (3)容错性:获得锁的进程若Crash,不影响到后续进程的正常获取锁 二 .解决方案 1. 最初的构想 在Java领域,同进程的多线程排他实现还是较简易的.比如使用线程同步变量标示是否已锁状态便可.但不同进程的排他实现就比较繁琐.使用已有API,自然想到 java.nio.channels.FileLock:如下 /** * @param file

  • Java 虚拟机(JVM)之基本概念详解

    1.类加载子系统:负责从文件系统或者网络中加载Class信息,加载的信息存放在一块称之为方法区的内存空间. 2.方法区:就是存放类信息.常量信息.常量池信息.包括字符串字面量和数字常量等.方法区是辅助堆栈的块永久区,解决堆栈信息的产生,是先决条件. 3.Java堆:再java虚拟机启动的时候建立Java堆,它是java程序最主要的内存工作区域,几乎所有的对象实例都存放到Java堆中,堆空间是所有线程共享的.堆解决的是数据存储问题,即数据怎么放.放在哪儿. 4.直接内存:Java的NIO库允许Ja

  • Java进程内缓存框架EhCache详解

    目录 一:目录 二: 简介 2.1.基本介绍 2.2.主要的特性 2.3. 集成 2.4. ehcache 和 redis 比较 三:事例 3.1.在pom.xml中引入依赖 3.2.在src/main/resources/创建一个配置文件 ehcache.xml 3.3.测试类 3.4.缓存配置 一:xml配置方式: 二:编程方式配置 3.5.Ehcache API 四:Spring整合 4.1.pom.xml 引入spring和ehcache 4.2.在src/main/resources添

  • java操作mongoDB查询的实例详解

    java操作mongo查询的实例详解 前言: MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的.他支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型.Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且

  • Java源码解析之TypeVariable详解

    TypeVariable,类型变量,描述类型,表示泛指任意或相关一类类型,也可以说狭义上的泛型(泛指某一类类型),一般用大写字母作为变量,比如K.V.E等. 源码 public interface TypeVariable<D extends GenericDeclaration> extends Type { //获得泛型的上限,若未明确声明上边界则默认为Object Type[] getBounds(); //获取声明该类型变量实体(即获得类.方法或构造器名) D getGenericDe

  • Java源码解析之GenericDeclaration详解

    学习别人实现某个功能的设计思路,来提高自己的编程水平.话不多说,下面进入正题. GenericDeclaration 可以声明类型变量的实体的公共接口,也就是说,只有实现了该接口才能在对应的实体上声明(定义)类型变量,这些实体目前只有三个:Class(类).Construstor(构造器).Method(方法)(详见:Java源码解析之TypeVariable详解 源码 public interface GenericDeclaration { //获得声明列表上的类型变量数组 public T

随机推荐