一、Socket 的使用

  1、单线程Socket的使用    

/**
* 单线程版本
* 问题描述:只能服务单个客户端
* 解决方案:多线程版本
*/
public class Socket_V1 {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(1234);
System.out.println("启动服务器:");
while(true) {
System.out.println("等待客户端链接(阻塞)……");
Socket socket = serverSocket.accept();
System.out.println("有链接进来了……");
handle(socket);
}
}
private static void handle(Socket socket) {
try {
InputStream inputStream = socket.getInputStream();
byte[] b = new byte[1024];
String str = null;
while(true) {
str = null;
System.out.println("等待输入……");
int read = inputStream.read(b);
if(read == -1) {
System.out.println("客户端关闭。");
break;
}
str = new String(b);
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

  2、多线程版本

/**
* 多线程版本
* 问题描述:多线程开销大
* 解决方案:NIO
*/
public class Socket_V2 { public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(1234);
// 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
ExecutorService threadPool = Executors.newFixedThreadPool(10);
System.out.println("启动服务器:");
while(true) {
System.out.println("等待客户端链接(阻塞)……");
final Socket socket = serverSocket.accept();
System.out.println("有链接进来了……");
//使用线程池来,支持并发
threadPool.execute(new Runnable() {
public void run() {
handle(socket);
}
});
}
}
private static void handle(Socket socket) {
try {
InputStream inputStream = socket.getInputStream();
byte[] b = new byte[1024];
String str = null;
while(true) {
str = null;
System.out.println("等待输入……");
int read = inputStream.read(b);
if(read == -1) {
System.out.println("客户端关闭。");
break;
}
str = new String(b);
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

  3、NIO

/**
* NIO版本
* 原理:IO多路复用
* NIO与旧Socket对比:
* ServerSocketChannel <-等价于-> ServerSocket
* SocketChannel <-等价于-> Socket
* Selector 选择器
* SelectionKey 事件类型
*/
public class Socket_NIO {
public static void main(String[] args) throws Exception {
//获得Socket通道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//将通道设置为非阻塞模式
serverSocketChannel.configureBlocking(false);
//将通道绑定到指定的端口
serverSocketChannel.socket().bind(new InetSocketAddress(1234));
//获取通道选择器
Selector selector = Selector.open();
//将连接事件,注册到选择器内(步骤1)
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("服务器启动成功。端口已经监听……");
while(true) {
selector.select();//阻塞等待已经注册的事件
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while(iterator.hasNext()) {
SelectionKey next = iterator.next();
iterator.remove();
if(next.isAcceptable()) { //如果是连接事件,注册读写事件
System.out.println("获取到连接事件。");
ServerSocketChannel sschannel = (ServerSocketChannel) next.channel(); //该强转是步骤1内存放的值
SocketChannel channel = sschannel.accept(); //获取客户端连接的通道
channel.configureBlocking(false);//设置为非阻塞
channel.register(selector, SelectionKey.OP_READ); //步骤2
}else if(next.isReadable()) { //如果是可读事件,则执行读操作
System.out.println("获取到可读事件。");
SocketChannel channel = (SocketChannel) next.channel(); //获取socket通道,该强转是步骤2内存放的值
ByteBuffer dst = ByteBuffer.allocate(1024); //缓冲区
int read = channel.read(dst);
if(read < 0 ) {
System.out.println("客户端关闭。");
next.cancel();
break;
}
System.out.println("客户端输入:"+new String(dst.array()));
} //还有其他事件……略
}
}
}
}

关于nio的一点理解:

  优点:少了线程切换的开销。(io多路复用)

    对比多线程模式,线程用完cpu时间片之后,就切换线程。 此时io阻塞的线程(不是就绪状态,无法获取cpu时间片),io非阻塞线程(网速很慢),只能获取到一部分数据,则浪费了相应的cpu时间片。 

NIO与Socket的更多相关文章

  1. 利用NIO建立Socket服务器

    传统的Java 的IO,利用Socket建立服务器,接收客户端连接,一般都是为每一个连接建立一个线程,如果连接数巨大,那么服务器开销也将巨大..NIO的原理,可以参照图:http://new.51ct ...

  2. 基于NIO的Socket通信

    一.NIO模式的基本原理: 服务端: 首先,服务端打开一个通道(ServerSocketChannel),并向通道中注册一个通道调度器(Selector):然后向通道调度器注册感兴趣的事件Select ...

  3. Java NIO 之 Socket Channel

    在Java NIO中用Channel来对程序与进行I/O操作主体的连接关系进行抽象,这些IO主体包括如文件.Socket或其他设备.简而言之,指代了一种与IO操作对象间的连接关系. 按照Channel ...

  4. NIO Channel Socket套接字相关Channel

    阻塞非阻塞: NIO中的Channel主要分为两大类:一类是FileChannel,另一类是SocketChannel.NIO提供的核心非阻塞特性主要针对SocketChannel类,全部socket ...

  5. Java I/O之NIO Socket

    PS:本文简单介绍下旧I/O和NIO下的Socket通讯,仅以UDP来示例. TCP/IP协议 首先简单回顾下TCP/IP协议 Application:应用程序:Socket:套接字:Host:主机: ...

  6. Java NIO4:Socket通道

    Socket通道 上文讲述了通道.文件通道,这篇文章来讲述一下Socket通道,Socket通道与文件通道有着不一样的特征,分三点说: 1.NIO的Socket通道类可以运行于非阻塞模式并且是可选择的 ...

  7. c.BIO连接器与NIO连接器的对比

    前面两节,我们分别看了BIO和NIO的两种模式Tomcat的实现方式. BIO的方式,就是传统的一线程,一请求的模式,也就是说,当同时又1000个请求过来,如果Tomcat设置了最大Accept线程数 ...

  8. Android NIO(Noblocking I/O非阻塞I/O)小结

    参考:http://www.cnblogs.com/cpcpc/archive/2011/06/27/2123009.html 对于Android的网络通讯性能的提高,我们可以使用Java上高性能的N ...

  9. 探索Java NIO

    什么是NIO? java.nio全称java non-blocking IO,是指jdk1.4 及以上版本里提供的新api(New IO),NIO提供了与标准IO不同的IO工作方式. 核心部分: Ch ...

随机推荐

  1. ElasticSearch速学 - IK中文分词器远程字典设置

    前面已经对”IK中文分词器“有了简单的了解:  但是可以发现不是对所有的词都能很好的区分,比如:  逼格这个词就没有分出来. 词库 实际上IK分词器也是根据一些词库来进行分词的,我们可以丰富这个词库. ...

  2. URL的组成和含义

    1.URL - Uniform Resource Locator 当您点击 HTML 页面中的某个链接时,对应的 <a>标签指向万维网上的一个地址. 统一资源定位器(URL)用于定位万维网 ...

  3. iOS9下UICollectionViewCell的awakeFromNib问题

    最近项目测试出一个隐藏已久的bug,经过多番测试,发现在iOS9下自定义的一个UICollectionViewCell只走一次awakeFromNib. 具体情况是,项目中有一个控制器用到了自定义的U ...

  4. leetcode-209-长度最小的子数组

    题目描述: 给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组.如果不存在符合条件的连续子数组,返回 0. 示例: 输入: s = 7, nums ...

  5. C#-WebForm-ajax状态保持

    cookies: ashx端赋值: context.Response.Cookies["Username"].Value = ""; 后台端加载: Respon ...

  6. QuantLib 金融计算——基本组件之 Date 类

    目录 QuantLib 金融计算--基本组件之 Date 类 Date 对象的构造 一些常用的成员函数 一些常用的静态函数 为估值计算配置日期 如果未做特别说明,文中的程序都是 Python3 代码. ...

  7. Flask-mail 发邮件慢(即使异步)

    Flask-mail 发邮件慢(即使异步) 一开始,按照狗书上的代码异步发邮件,但是发现原本响应只需要150ms的页面加了邮件发送就变成了5s响应(这怕不是假异步) 狗书的异步发邮件代码: def s ...

  8. 03-树3 Tree Traversals Again (25 分)

    An inorder binary tree traversal can be implemented in a non-recursive way with a stack. For example ...

  9. 修改VS项目的目标平台(目标框架)

    如果是正常的情况下.. 右键项目属性里就有修改的地方.. 可是有时候打开属性发现修改的下拉框是禁用的.. 这时候可以右键 "卸载项目" 编辑 .csproj 项目文件 在上方有个& ...

  10. java使用freemarker生成word文档

    1.原料 开源jar包freemarker.eclipse.一份模板word文档 2.首先设计模板word文档 一般,通过程序输出的word文档的格式是固定的,例如建立一个表格,将表格的标题写好,表格 ...