在传统的Java 网络编程中,对于客户端的每次连接,对于服务器来说,都要创建一个新的线程与客户端进行通讯,这种频繁的线程的创建,对于服务器来说,是一种巨大的损耗,在Java 1.4 引入Java nio 引入了 selector channel buffer 对此操作进行重新的定义:

服务端:

package com.java.baseknowledge.net;

import java.io.IOException;
import java.net.InetAddress;
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.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.Set; public class NioService {
//store userMap
public static Map<Integer,SocketChannel> userMap =new HashMap<>();
public static void main(String[] args) throws Exception { //selector object
Selector selector =Selector.open();
//serversocketchannel object is listening client accept
ServerSocketChannel serverSocket =ServerSocketChannel.open();
//Adjusts this channel's blocking mode.
serverSocket.configureBlocking(false); serverSocket.bind(new InetSocketAddress(9099));
//在selector中register channel
serverSocket.register(selector, SelectionKey.OP_ACCEPT); while(true) {
//block method event listening,this method is perform when event is touch;
selector.select();
//get selection-key set
Set<SelectionKey> selectedKeys = selector.selectedKeys(); selectedKeys.forEach((keys->{
//judge selectionkey mode
if(keys.isAcceptable()) {
try {
ServerSocketChannel channel = (ServerSocketChannel)keys.channel();
//obtain socketchannel
SocketChannel accept = channel.accept();
accept.configureBlocking(false);
//regist selector,listening read event
accept.register(selector, SelectionKey.OP_READ);
userMap.put(new Random().nextInt()*new Random().nextInt(), accept); }
catch(Exception e ) {
e.printStackTrace();
}
} else if(keys.isReadable()) {
//obtain socketchannel
try {
SocketChannel channel = (SocketChannel)keys.channel();
System.out.println(channel);
ByteBuffer by = ByteBuffer.allocate(2048);
channel.read(by); userMap.forEach((k,v)->{ by.rewind();
if(v!=channel) {
try {
v.write(by);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}); }
catch(Exception e) {} }
selectedKeys.clear(); })); } } }

客户端:

package com.java.baseknowledge.net;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; /**
* chat client
* @author Administrator
*
*/
public class JavaNioClient { public static void main(String[] args) throws Exception { //建立Selector
Selector selector =Selector.open();
SocketChannel socketChannel=SocketChannel.open();
//设置非阻塞
socketChannel.configureBlocking(false); socketChannel.register(selector, SelectionKey.OP_CONNECT); socketChannel.connect(new InetSocketAddress("127.0.0.1", 9099)); while(true) {
selector.select(); Set<SelectionKey> setionkey =selector.selectedKeys(); for(SelectionKey kk :setionkey) {
if(kk.isConnectable()) {
//从selectionkey 获取socketChannel
SocketChannel socket=(SocketChannel)kk.channel();
//手动建立连接
if(socket.isConnectionPending()) {
socket.finishConnect();
//写数据
ByteBuffer byteB = ByteBuffer.allocate(1024);
byteB.put((System.currentTimeMillis()+"连接ok").getBytes());
byteB.flip();
socket.write(byteB);
//jdk1.5 线程池
ExecutorService exe =Executors.newSingleThreadExecutor(Executors.defaultThreadFactory()); exe.submit(new Thread() { @Override
public void run() {
while(true) {
String msg=null;
byteB.clear();
//标准键盘输入
BufferedReader br =new BufferedReader(new InputStreamReader(System.in));
try {
msg =br.readLine();
ByteBuffer bytec = ByteBuffer.allocate(1024);
bytec.put(msg.getBytes());
bytec.flip();
socket.write(bytec);
} catch (IOException e) { e.printStackTrace();
}
}
}
});
} socket.register(selector, SelectionKey.OP_READ);
}
else if(kk.isReadable()) { //从selectionkey 获取socketChannel
SocketChannel socket=(SocketChannel)kk.channel();
ByteBuffer by =ByteBuffer.allocate(1024);
int a=socket.read(by);
//if(a>0) {
String receive =new String(by.array());
System.out.println(receive);
//}
} setionkey.clear();
} } } }

java 基础之--nio 网络编程的更多相关文章

  1. JAVA基础知识之网络编程——-网络基础(Java的http get和post请求,多线程下载)

    本文主要介绍java.net下为网络编程提供的一些基础包,InetAddress代表一个IP协议对象,可以用来获取IP地址,Host name之类的信息.URL和URLConnect可以用来访问web ...

  2. Java基础教程:网络编程

    Java基础教程:网络编程 基础 Socket与ServerSocket Socket又称"套接字",网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个s ...

  3. java基础学习总结——网络编程

    一.网络基础概念 首先理清一个概念:网络编程 != 网站编程,网络编程现在一般称为TCP/IP编程.

  4. Java 基础高级2 网络编程

    1.协议的概念:通信双方事先约定好的通信规则 2七层网络通信协议:应用成,表示层,会话层,传输层,网络层,数据链路层 3.TCP/IP协议:点对点通信,三层握手,安全有保证 4.UDP协议;广播协议, ...

  5. JAVA基础知识之网络编程——-网络通信模型(IO模型)

    <Unix网络编程:卷1>中介绍了5中I/O模型,JAVA作为运行在宿主机上的程序,底层也遵循这5中I/O模型规则.这5中I/O模型分别是: 阻塞式IO 非阻塞式IO I/O复用 信号驱动 ...

  6. 【java基础学习】网络编程

    网络编程 InetAddress tcp udp

  7. 【Java基础总结】网络编程

    网络编程 InetAddress tcp udp

  8. JAVA基础知识之网络编程——-基于NIO的非阻塞Socket通信

    阻塞IO与非阻塞IO 通常情况下的Socket都是阻塞式的, 程序的输入输出都会让当前线程进入阻塞状态, 因此服务器需要为每一个客户端都创建一个线程. 从JAVA1.4开始引入了NIO API, NI ...

  9. JAVA基础知识之网络编程——-基于UDP协议的通信例子

    UDP是一种不可靠的协议,它在通信两端各建立一个socket,这两个socket不会建立持久的通信连接,只会单方面向对方发送数据,不检查发送结果. java中基于UDP协议的通信使用DatagramS ...

随机推荐

  1. 与前端对接 jsonp

    主要是回调的写法,前端人员接受的数据格式      参数 (jsonString);

  2. cxGrid 颜色设置

    一.cxGrid 根据列值变色(样式) 在使用cxGrid的过程中,某一个单元格经常需要根据其他单元格的值来做相应的变色,如: 在cxGridDBTableView中,选定要变样式(如背景色.字体属性 ...

  3. MySQL null与not null和null与空值''的区别

    参考连接:https://segmentfault.com/a/1190000009540449 相信很多用了MySQL很久的人,对这两个字段属性的概念还不是很清楚,一般会有以下疑问: 我字段类型是n ...

  4. Haskell语言学习笔记(70)NonEmpty

    NonEmpty(非空列表) infixr 5 :| data NonEmpty a = a :| [a] deriving (Eq, Ord) instance Functor NonEmpty w ...

  5. mysql 设置多个字段聚合自增

    DROP TEMPORARY TABLE IF EXISTS ttp_firstInvest; CREATE TEMPORARY TABLE ttp_firstInvest ( userid varc ...

  6. angularjs 请求数据转换为Form Data传参

    在angularjs中配置好服务,有时传参会导致后台借不到值或者后台直接报错: 这就与后台框架有关,如果后台是以public ModelAndView接收接口传过来的参数,这种情况,前台传参的形式比较 ...

  7. git 恢复到旧版本命令

    1.第一步:找到你想恢复到的版本号:可以在git提交日志中查看-> 找到版本号,复制下来,在git项目根目录下打开git命令窗口: 输入:git reset --hard xxxxxxxxxxx ...

  8. springboot 引入 thymeleaf 模板

    第一步pom中: <!-- 引入 thymeleaf 模板依赖 --> <dependency> <groupId>org.springframework.boot ...

  9. pip 离线安装

    pip download ansible -d . --trusted-host mirrors.aliyun.com pip install ansible-2.7.5.tar.gz  --user ...

  10. React设置宽度的坑

    [React设置宽度的坑] 我们知道通过ref可以获取DOM元素,通过style属性可以给此DOM元素添加样式. 但下面两行的赋值是无效的: this.HomeRootDiv.style.width= ...