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的更多相关文章

  1. java基础-网络编程(Socket)技术选型入门之NIO技术

    java基础-网络编程(Socket)技术选型入门之NIO技术 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.传统的网络编程 1>.编写socket通信的MyServer ...

  2. Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制

    Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制 JAVA 中原生的 socket 通信机制 摘要:本文属于原创,欢迎转载,转载请保留出处:https://github.co ...

  3. Java nio socket与as3 socket(粘包解码)连接的应用实例

    对Java nio socket与as3 socket连接的简单应用 <ignore_js_op>Java nio socket与as3 socket连接的应用实例.rar (9.61 K ...

  4. NIO【同步非阻塞io模型】关于 NIO socket 的详细总结【Java客户端+Java服务端 + 业务层】【可以客户端间发消息】

    1.前言 以前使用 websocket来实现双向通信,如今深入了解了 NIO 同步非阻塞io模型 , 优势是 处理效率很高,吞吐量巨大,能很快处理大文件,不仅可以 做 文件io操作, 还可以做sock ...

  5. 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 ...

  6. 深入浅出NIO Socket实现机制

    前言 Java NIO 由以下几个核心部分组成: Buffer Channel Selector 以前基于net包进行socket编程时,accept方法会一直阻塞,直到有客户端请求的到来,并返回so ...

  7. java与C++之间进行SOCKET通讯要点简要解析

    原文链接: http://blog.csdn.net/hslinux/article/details/6214594 java与C++之间进行SOCKET通讯要点简要解析 hslinux 0.篇外语 ...

  8. Java网络编程和NIO详解开篇:Java网络编程基础

    Java网络编程和NIO详解开篇:Java网络编程基础 计算机网络编程基础 转自:https://mp.weixin.qq.com/s/XXMz5uAFSsPdg38bth2jAA 我们是幸运的,因为 ...

  9. Java网络编程和NIO详解8:浅析mmap和Direct Buffer

    Java网络编程与NIO详解8:浅析mmap和Direct Buffer 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Java网络编程和NI ...

随机推荐

  1. 实时跟踪log变化的工具Apachetop

    作为一个网站管理员,我们经常会有需要知道当前什么人正在访问我们的网站,谁正在频繁的抓取我们网站的内容,什么搜索引擎正在抓取我们网站?面对这些问题,我们虽然可以去查看log日志文件,但是却不能让我们实时 ...

  2. Competing Consumers Pattern (竞争消费者模式)

    Enable multiple concurrent consumers to process messages received on the same messaging channel. Thi ...

  3. 05-Java中的String类

    程序设计思路: 首先目标是使输入的字符串加上某个数变成另一个字符串,从而相当于对字符串进行加密. 第一步输入一个字符串String类型: 第二步把这个字符串转变成字符数组: 第三步让这个数组的每一个字 ...

  4. Oracle job定时器的执行时间间隔学习汇总

      Oracle job 定时器的执行时间间隔也是定时器job 的关键设置,在这一设置上,开始还没掌握,总是不知道怎么写,现总结如下,其实主要是使用了TRUNC.NEXT_DAY .ADD_MONTH ...

  5. js功能汇总

    请编写一个JavaScript 函数toRGB,它的作用是转换CSS中常用的颜色编码. 要求: 1 alert(toRGB("#0000FF")); // 输出 rgb(0, 0, ...

  6. Google工程师打造Remix OS系统 桌面版安卓下载

    三位前Google工程师打造的Remix OS系统终于来到了PC桌面上,现已可以下载尝鲜. Remix OS for PC基于Android-x86项目,由安卓5.1 Lollipop深度定制而来,不 ...

  7. Objective-C运行时编程 - 方法混写 Method Swizzling

    摘要: 本文描述方法混写对实例.类.父类.不存在的方法等情况处理,属于Objective-C(oc)运行时(runtime)编程范围. 编程环境:Xcode 6.1.1, Yosemite,iOS 8 ...

  8. Angular19 自定义表单控件

    1 需求 当开发者需要一个特定的表单控件时就需要自己开发一个和默认提供的表单控件用法相似的控件来作为表单控件:自定义的表单控件必须考虑模型和视图之间的数据怎么进行交互 2 官方文档 -> 点击前 ...

  9. Telephone Lines [POJ3662] [二分答案]

    Description Farmer John打算将电话线引到自己的农场,但电信公司并不打算为他提供免费服务.于是,FJ必须为此向电信公司支付一定的费用. FJ的农场周围分布着N(1 <= N ...

  10. myeclipse、maven、tomcat、jdk技巧和坑【待完善】

    公司使用前后不分离或半分离的springmvc + maven ,自己不得不研究研究myeclipse.maven.tomcat等等 开发环境搭建:坑一: Unable to process Jar ...