一:介绍:

IO:阻塞IO网络模型:服务器启动后会进入阻塞状态,等待client连接,每一个client端连接上服务器后,服务器会为每一个客户端起一个线程来处理客户端的需求。服务器的accept()方法、服务器新起的thread中,Socket的read()和write()方法都是阻塞的。

NIO-Single Thread模型:NIO单线程模型:采用selector管理的轮询查询模式,selector每隔一段时间都去看一下client端有没有产生需要处理的消息(客户端连接请求、客户端发送数据请求、客户端下载数据请求),也就是说selector会同时管理client端的连接和通道内client端的读、写请求。

NIO-reactor模式:在NIO单线程模式中,只有一个线程负责处理client端的连接和通道内client端的读、写请求。在reactor模式中,将server端的单线程换成线程池(单线程管家+线程池工人模式)。

  • NIO在单线程下可以同时为多个客户端服务
  • NIO技术直接将 read buffer 拷贝到 socket buffer. java 的 FileChannel.transferTo() 方法就是这样的实现, 这个实现是依赖于操作系统底层的sendFile()实现的.

二:实例:

1.新建两个java项目 ,一个作为client端,一个作为serve端

serve端代码:

package com.company;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;public class Main {public static void main(String[] args) throws IOException {//创建客户端的Socket对象(SevereSocket)//ServerSocket (int port)创建绑定到指定端口的服务器套接字ServerSocket ss=new ServerSocket(50000);//Socket accept()侦听要连接到此套接字并接受他Socket s=ss.accept();//获取输入流,读数据,并把数据显示在控制台InputStream is=s.getInputStream();byte[] bys=new byte[1024];int len=is.read(bys);String data=new String(bys,0,len);System.out.println("client:"+data);//释放资源s.close();ss.close();}
}

client端代码展示:

package com.company;import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;public class Main{public static void main(String[] args) throws IOException{//创建客户端的Socket对象//Socket (InetAddress adress,int port)创建流套接字并将其连接到指定IP地址的指定端口号
//      Socket s=new Socket(InetAddress.getByName("192.168.224.1"), 10000);//Socket (String host,int port)创建流套接字并将其连接到指定主机的指定端口号Socket s=new Socket("127.0.0.1", 50000);//获取输出流,写数据//OutputStream getOutputStream();返回此套接字的输出流OutputStream os=s.getOutputStream();os.write("hello wxc 6319xxxx119,tcp".getBytes());//释放资源s.close();}}

运行结果:

2. NIO端同样新建JAVA项目:

Serve端代码:

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;public class server {//网络通信IO操作,TCP协议,针对面向流的监听套接字的可选择通道(一般用于服务端)private ServerSocketChannel serverSocketChannel;private Selector selector;/**开启服务端*/public void start(Integer port) throws Exception {serverSocketChannel = ServerSocketChannel.open();selector = Selector.open();//绑定监听端口serverSocketChannel.socket().bind(new InetSocketAddress(port));//设置为非阻塞模式serverSocketChannel.configureBlocking(false);//注册到Selector上serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);startListener();}private void startListener() throws Exception {while (true) {// 如果客户端有请求select的方法返回值将不为零if (selector.select(1000) == 0) {System.out.println("current not exists task");continue;}// 如果有事件集合中就存在对应通道的keySet<SelectionKey> selectionKeys = selector.selectedKeys();Iterator<SelectionKey> iterator = selectionKeys.iterator();// 遍历所有的key找到其中事件类型为Accept的keywhile (iterator.hasNext()) {SelectionKey key = iterator.next();if (key.isAcceptable())handleConnection();if (key.isReadable())handleMsg(key);iterator.remove();}}}/*** 处理建立连接*/private void handleConnection() throws Exception {SocketChannel socketChannel = serverSocketChannel.accept();socketChannel.configureBlocking(false);socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));}/** 接收信息*/private void handleMsg(SelectionKey key) throws Exception {SocketChannel channel = (SocketChannel) key.channel();ByteBuffer attachment = (ByteBuffer) key.attachment();channel.read(attachment);System.out.println("current msg: " + new String(attachment.array()));}public static void main(String[] args) throws Exception {server myServer = new server();myServer.start(8888);}
}

client端代码;

package com.company;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;public class Main {public static void main(String[] args) throws Exception {SocketChannel socketChannel = SocketChannel.open();socketChannel.configureBlocking(false);// 连接服务器if (!socketChannel.connect(new InetSocketAddress("127.0.0.1", 8888))) {while (!socketChannel.finishConnect()) {System.out.println("connecting...");}}//发送数据String str = "hello wxc 6319xxxx119";ByteBuffer byteBuffer = ByteBuffer.wrap(str.getBytes());socketChannel.write(byteBuffer);System.in.read();}}

3.netty端:

同理新建项目,导入相应的包:

serve端:

package com.company;import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;import java.net.InetSocketAddress;/****/
public class Main {private int port;public static void main(String[] args){new Main(18080).start();}public Main(int port) {this.port = port;}public void start() {/*** 创建两个EventLoopGroup,即两个线程池,boss线程池用于接收客户端的连接,* 一个线程监听一个端口,一般只会监听一个端口所以只需一个线程* work池用于处理网络连接数据读写或者后续的业务处理(可指定另外的线程处理业务,* work完成数据读写)*/EventLoopGroup boss = new NioEventLoopGroup(1);EventLoopGroup work = new NioEventLoopGroup();try {/*** 实例化一个服务端启动类,* group()指定线程组* channel()指定用于接收客户端连接的类,对应java.nio.ServerSocketChannel* childHandler()设置编码解码及处理连接的类*/ServerBootstrap server = new ServerBootstrap().group(boss, work).channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port)).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast("decoder", new StringDecoder()).addLast("encoder", new StringEncoder()).addLast(new HelloWorldServerHandler());}});//绑定端口ChannelFuture future = server.bind().sync();System.out.println("server started and listen " + port);future.channel().closeFuture().sync();} catch (Exception e) {e.printStackTrace();}finally {boss.shutdownGracefully();work.shutdownGracefully();}}public static class HelloWorldServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {System.out.println("HelloWorldServerHandler active");}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {System.out.println("server channelRead..");System.out.println(ctx.channel().remoteAddress()+"->Server :"+ msg.toString());ctx.write("server write"+msg);ctx.flush();}}
}

client端:

package com.company;import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;/****/
public class Main {private static final String HOST = "localhost";private static final int PORT= 18080;public static void main(String[] args){new Main().start(HOST, PORT);}public void start(String host, int port) {EventLoopGroup group = new NioEventLoopGroup();try {Bootstrap client = new Bootstrap().group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true).handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast("decoder", new StringDecoder()).addLast("encoder", new StringEncoder()).addLast(new HelloWorldClientHandler());}});ChannelFuture future = client.connect(host, port).sync();future.channel().writeAndFlush("Hello Netty Server ,I am a netty client");future.channel().closeFuture().sync();} catch (Exception e) {e.printStackTrace();} finally {group.shutdownGracefully();}}public static class HelloWorldClientHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {System.out.println("HelloWorldClientHandler Active");}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {System.out.println("HelloWorldClientHandler read Message:"+msg);}}
}

运行结果:

基于IO、NIO、Netty聊天程序相关推荐

  1. Netty聊天程序(2):从0开始实战100w级流量应用 - 图解Netty系列

    客户端 Client 登录和响应处理 疯狂创客圈 Java 分布式聊天室[ 亿级流量]实战系列之 17[ 博客园 总入口 ] 文章目录 客户端 Client 登录和响应处理 写在前面 客户端的会话管理 ...

  2. 基于TCP协议网上聊天程序(python)带界面

    基于TCP协议网上聊天程序(python)带界面 1 设计目标 基于TCP协议网上聊天程序 实现一简单的聊天程序实现网上聊天,包括服务器和客户端. (1)支持多人聊天: (2)客户端具有图形化用户界面 ...

  3. 计算机网络课程设计--基于TCP协议网上聊天程序--python实现带图形界面--socket--多线程

                                              基于TCP协议网上聊天程序 引言 21世纪是一个以网络为核心的信息时代,要实现信息化,就必须依靠完善的网络.而随着计 ...

  4. java tcp聊天程序_java实现基于Tcp的socket聊天程序

    对于步入编程行业不深的初学者或是已经有所领会的人来说,当学习一项新的技术的时候,非常渴望有一个附上注释完整的Demo.本人深有体会,网上的例子多到是很多,但是很杂不完整,写代码这种东西来不得半点马虎, ...

  5. 利用TCP和UDP协议,实现基于Socket的小聊天程序(初级版)

    TCP TCP (Transmission Control Protocol)属于传输层协议.其中TCP提供IP环境下的数据可靠传输,它提供的服务包括数据流传送.可靠性.有效流控.全双工操作和多路复用 ...

  6. Java案例:基于TCP的简单聊天程序

    文章目录 一.如何实现TCP通信 二.编写C/S架构聊天程序 (一)编写服务器端程序 - Server.java (二)编写客户端程序 - Client.java (三)测试服务器端与客户端能否通信 ...

  7. 基于TCP的在线聊天程序

    在线聊天服务端 import tkinter import tkinter.font as tkFont import socket import threading import time impo ...

  8. 分别基于IO、NIO、Netty的Java网络程序

    分别基于IO.NIO.Netty的Java网络程序 IDE:IntelliJ IDEA 文章目录 分别基于IO.NIO.Netty的Java网络程序 一.Java NIO 1.1 NIO与传统IO对比 ...

  9. 利用TCP传输协议实现基于Socket的聊天程序(高级版_多线程)

    大家好,在上篇<利用TCP和UDP协议,实现基于Socket的小聊天程序(初级版)>博客中,所写程序只是实现简单的连接通信,基于控制台实现,运用了TCP和UDP两种传输协议.今天我和大家分 ...

  10. Java实验:编写网络聊天程序(图形界面)

    课程名称 高级Java程序设计 实验项目 Java网络编程 实验目的: 使用客户机/服务器模式.基于TCP协议编写一对多"群聊"程序.其中客户机端单击"连接服务器&quo ...

最新文章

  1. 打开阿兹海默之门:华裔张复伦利用RNN成功解码脑电波,合成语音 | Nature
  2. Spring Cloud Gateway CORS 方案看这篇就够了
  3. [置顶] 自己动手实现OpenGL-OpenGL原来如此简单(二)
  4. IP Precedence DSCP、TOS
  5. Web 仿 App 动画竟然引出了“性能杀手”
  6. python字符串大全_python学习笔记:字符串操作大全
  7. 《面向对象的思考过程(原书第4版)》一1.11 组合
  8. influxdb连续查询CQ和保留策略RP
  9. linux fdisk 分区
  10. mouseover 和 hover 方法
  11. KKK下拉框lookupedit绑定数据时,添加一条固定数据
  12. overlay/static/register/atuo/extern/volatile/const 修饰符的用法
  13. ajax jsonp跨域访问,jquery ajax怎么使用jsonp跨域访问
  14. 陈述句c语言,幼儿语言发展中最早产生的句型是()。A.陈述句 B.疑问句C.祈使句 D.感叹句...
  15. 虚拟服务器网络未识别,vm虚拟机未识别的网络
  16. 图论——最短路径之渡河问题
  17. 如何在WPS中给一组字母上方添加一个横线
  18. pytorch股票预测
  19. Python3 (基础练习) 一球从100米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在第10次落地时,共经过多少米?第10次反弹多高?
  20. 联邦学习框架 FederatedScope(1)快速入门

热门文章

  1. linux命令入门教程视频,linux命令入门视频教程
  2. 前端的学习之路:初级CSS---奔跑的少年(动画练习)
  3. 8086汇编语言寄存器清零学习
  4. 公式编辑器中如何加粗部分变量Ps:如向量。
  5. 使用httpclient模拟登陆
  6. Subversion Edge管理员密码找回
  7. 不黑艺术学社孙溟㠭匪石集中创作一周
  8. 不是吧 不是吧 还有比B+Tree更快的一种查询结构
  9. vue element-ui之怎么封装一个自己的组件
  10. 通达信换手率指标公式,衡量股票的活跃程度