Java I/O之NIO Socket
PS:本文简单介绍下旧I/O和NIO下的Socket通讯,仅以UDP来示例。
TCP/IP协议
首先简单回顾下TCP/IP协议 
Application:应用程序;Socket:套接字;Host:主机;Channel:通信信道;Ethernet:以太网;Router:路由器;Network Layer:网络层;Transport Layer:传输层。
在TCP/IP协议族中,底层由基础的通信信道构成,如以太网或调制解调器拨号连接。这些信道由网络层(network layer)使用,而网络层则完成将分组报文传输到它们的目的地址的工作(也就是路由器的功能)。TCP/IP协议族中属于网络层的唯一协议是IP协议,它使两个主机间的一系列通信信道和路由器看起来像是一条单一的主机到主机的信道。
IP协议提供了一种数据报服务:每组分组报文都由网络独立处理和分发,就像信件或包裹通过邮政系统发送一样。为了实现这个功能,每个IP报文必须包含一个保存其目的地址(address)的字段,就像你所投递的每份包裹都写明了收件人地址。(我们随即会对地址进行更详细的说明。)尽管绝大部分递送公司会保证将包裹送达,但IP协议只是一个"尽力而为"(best-effort)的协议:它试图分发每一个分组报文,但在网络传输过程中,偶尔也会发生丢失报文,使报文顺序被打乱,或重复发送报文的情况。
IP协议层之上称为传输层(transport layer)。它提供了两种可选择的协议:TCP协议和UDP协议。这两种协议都建立在IP层所提供的服务基础上,但根据应用程序协议(application protocols)的不同需求,它们使用了不同的方法来实现不同方式的传输。TCP协议和UDP协议有一个共同的功能,即寻址。回顾一下,IP协议只是将分组报文分发到了不同的主机,很明显,还需要更细粒度的寻址将报文发送到主机中指定的应用程序,因为同一主机上可能有多个应用程序在使用网络。TCP协议和UDP协议使用的地址叫做端口号(port numbers),都是用来区分同一主机中的不同应用程序。TCP协议和UDP协议也称为端到端传输协议(end-to-end transport protocols),因为它们将数据从一个应用程序传输到另一个应用程序,而IP协议只是将数据从一个主机传输到另一主机。
TCP协议能够检测和恢复IP层提供的主机到主机的信道中可能发生的报文丢失、重复及其他错误。TCP协议提供了一个可信赖的字节流(reliable byte-stream)信道,这样应用程序就不需要再处理上述的问题。TCP协议是一种面向连接(connection-oriented)的协议:在使用它进行通信之前,两个应用程序之间首先要建立一个TCP连接,这涉及到相互通信的两台电脑的TCP部件间完成的握手消息(handshake messages)的交换。使用TCP协议在很多方面都与文件的输入输出(I/O, Input/Output)相似。实际上,由一个程序写入的文件再由另一个程序读取就是一个TCP连接的适当模型。另一方面,UDP协议并不尝试对IP层产生的错误进行修复,它仅仅简单地扩展了IP协议"尽力而为"的数据报服务,使它能够在应用程序之间工作,而不是在主机之间工作。因此,使用了UDP协议的应用程序必须为处理报文丢失、顺序混乱等问题做好准备。
旧I/O的Socket示例
//服务器端
DatagramSocket servSocket = null;
byte[] buf = new byte[1024];
DatagramPacket datapkg = new DatagramPacket(buf, buf.length);
try {
servSocket = new DatagramSocket(5008);
while (true) {
servSocket.receive(datapkg);
//一般使用多线程来处理....
System.out.println("服务器接收了客户端:" + datapkg.getAddress()
+ " 的数据:" + new String(buf, 0, datapkg.getLength()));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
servSocket.close();
}
//客户端
DatagramSocket clientSocket=new DatagramSocket();
byte[] msg="this is a test message".getBytes();
DatagramPacket datapkg=new DatagramPacket(msg, msg.length, new InetSocketAddress("127.0.0.1", 5008));
clientSocket.send(datapkg);
clientSocket.close();
上面只是简单地示例,实际用应用中需要多线程,特别是服务器端,接收到数据报文后一般需要使用多线程来处理的。
NIO的Socket
旧I/O Socket是阻塞式的,我们通过上例可以看到使用了while(true)在那忙等(很傻吧),当然你可以使用多线程来避开阻塞,但这个解决办法会产生它自己的问题 ― 即线程开销,线程开销同时影响性能和可伸缩性。
新NIO Socket可以使用非阻塞式的(如果你一定要把NIO Socket用作阻塞式的,也不会有人拦你的^_^),实际上是采取Reactor模式,或者说是Observer模式为我们监察I/O端口,如果有内容进来,就会帮我们记录下来,当我们需要的时候再取出来,这样,我们就不必开启多个线程死等,从外界看,实现了流畅的I/O读写,不堵塞了。
而这个非阻塞模式就是由NIO中的类Selector来完成的,它类似一个观察者:只要我们把需要探知的channel事件注册到Selector上,我们接着做别的事情,当channel有事件发生时就会主动通知selector,我们可以轮询selector就知道那些channel可操作,然后我们再从这个Channel中读取数据,放心,包准能够读到,接着我们可以处理这些数据。
NIO中的通道和缓冲器在前面一篇博文中有介绍,我们来看下非阻塞式的代码示例
// 服务器端
DatagramChannel servChannel = DatagramChannel.open();
servChannel.socket().bind(new InetSocketAddress("127.0.0.1", 5008));
// 如果使用selector,此处必须设置为非阻塞式的
servChannel.configureBlocking(false); ByteBuffer buf = ByteBuffer.allocate(1024); Selector selector = Selector.open();
// 注册事件OP_ACCEPT和OP_CONNECT用于TCP,OP_READ和OP_WRITE可用于UDP和TCP
servChannel.register(selector, SelectionKey.OP_READ); // 轮询selector
while (true) {
if (selector.select() > 0) {
Iterator<SelectionKey> it = selector.selectedKeys().iterator();
while (it.hasNext()) {
SelectionKey key = it.next();
if (key.isReadable()) {
buf.clear();
SocketAddress clientAdrress = ((DatagramChannel) key
.channel()).receive(buf);
buf.flip();
System.out.println("服务器接收了客户端:" + clientAdrress
+ " 的数据:" + buf.asCharBuffer());
}
it.remove();
}
}
}
虽然说得天花乱坠,但到目前为止我还是没太明白使用这种观察者模式的好处,最后还是避不开忙等。(PS:关于I/O Socket和NIO Socket的对比优势可参考这里。)
推荐一本书:《Java Tcp/Ip Socket编程》
Java I/O之NIO Socket的更多相关文章
- java基础-网络编程(Socket)技术选型入门之NIO技术
java基础-网络编程(Socket)技术选型入门之NIO技术 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.传统的网络编程 1>.编写socket通信的MyServer ...
- Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制
Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制 JAVA 中原生的 socket 通信机制 摘要:本文属于原创,欢迎转载,转载请保留出处:https://github.co ...
- Java nio socket与as3 socket(粘包解码)连接的应用实例
对Java nio socket与as3 socket连接的简单应用 <ignore_js_op>Java nio socket与as3 socket连接的应用实例.rar (9.61 K ...
- NIO【同步非阻塞io模型】关于 NIO socket 的详细总结【Java客户端+Java服务端 + 业务层】【可以客户端间发消息】
1.前言 以前使用 websocket来实现双向通信,如今深入了解了 NIO 同步非阻塞io模型 , 优势是 处理效率很高,吞吐量巨大,能很快处理大文件,不仅可以 做 文件io操作, 还可以做sock ...
- Java I/O and NIO [reproduced]
Java I/O and NIO.2---Five ways to maximize Java NIO and NIO.2---Build more responsive Java applicati ...
- 深入浅出NIO Socket实现机制
前言 Java NIO 由以下几个核心部分组成: Buffer Channel Selector 以前基于net包进行socket编程时,accept方法会一直阻塞,直到有客户端请求的到来,并返回so ...
- java与C++之间进行SOCKET通讯要点简要解析
原文链接: http://blog.csdn.net/hslinux/article/details/6214594 java与C++之间进行SOCKET通讯要点简要解析 hslinux 0.篇外语 ...
- Java网络编程和NIO详解开篇:Java网络编程基础
Java网络编程和NIO详解开篇:Java网络编程基础 计算机网络编程基础 转自:https://mp.weixin.qq.com/s/XXMz5uAFSsPdg38bth2jAA 我们是幸运的,因为 ...
- Java网络编程和NIO详解8:浅析mmap和Direct Buffer
Java网络编程与NIO详解8:浅析mmap和Direct Buffer 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Java网络编程和NI ...
随机推荐
- Unity UGUI —— 无限循环List
还记得大学毕业刚工作的时候是做flash的开发,那时候看到别人写的各种各样的UI组件就非常佩服,后来自己也慢慢尝试着写,发现其实也就那么回事.UI的开发其实技术的成分相对来说不算多,但是一个好的UI是 ...
- Selenium关于Page Objects
介绍页面对象设计模式.一个页面对象表示在你测试的web页面用户交互的界面. 使用页面对象模式的有点: 创建可重用的代码可以在多个测试用例中使用 减少重复的代码量 如果用户界面改变,只需要修改一个地方 ...
- 2.7. 属性的各种设置选项(Core Data 应用程序实践指南)
可供配置的选项根据属性类型的不同有所变化,并不是每一种属性都能配置下列选项 Transient:勾选该选项,表示该属性不写入“持久化存储区”,这听起来很奇怪,但有时候,只需要把特性留在托管对象上下文就 ...
- centos 用户管理
3.使用命令管理账户 useradd 选项 用户名//添加新用户 usermod 选项 用户名//修改已经存在的用户 userdel -r 用户名//删除用户表示自家目录一起删除. grou ...
- EF Code First:实体映射
二.实体映射 实体与数据库的映射可以通过DataAnnotation与FluentAPI两种方式来进行映射: (一) DataAnnotation DataAnnotation 特性由.NET 3.5 ...
- 用mfix模拟流化床时压力边界条件和迭代步长需要注意的问题
没想到今天模拟一个冷态流化床都出现这么多问题.需要通入三种气体组成的混合物,这时入口边界的压力BC_P_g不能为零,否则会报错,但是,需要注意的是,收敛效果对这个压力边界非常敏感,我随意给了个30,结 ...
- 10款面向HTML5 画布(Canvas)的JavaScript库
https://www-evget-com/article/2014/4/9/20799.html
- Beanstalkd使用
Beanstalkd,一个高性能.轻量级的分布式内存队列系统,最初设计的目的是想通过后台异步执行耗时的任务来降低高容量Web应用系统的页面访问延迟,支持过有9.5 million用户的Facebook ...
- GreenOpenPaint的实现(一)基本框架
Win7下的MSPaint是Ribbon的典型运行.这种SDI程序对于图像处理来说是很适合的.利用春节时间,基于之前的积累,我实现GreenOpenPaint,主要就是模拟MSPaint的界面,实现出 ...
- codeforces div2.C
C. New Year and Rating time limit per test 2 seconds memory limit per test 256 megabytes input stand ...