first commit
This commit is contained in:
3
io-study-master/io-study/.gitignore
vendored
Normal file
3
io-study-master/io-study/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/.idea
|
||||
/*.iml
|
||||
/target
|
||||
45
io-study-master/io-study/pom.xml
Normal file
45
io-study-master/io-study/pom.xml
Normal file
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.example</groupId>
|
||||
<artifactId>io-study</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- netty -->
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<version>4.1.35.Final</version>
|
||||
</dependency>
|
||||
|
||||
<!-- lombok -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.12</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>8</source>
|
||||
<target>8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
60
io-study-master/io-study/src/main/java/bio/SocketServer.java
Normal file
60
io-study-master/io-study/src/main/java/bio/SocketServer.java
Normal file
@@ -0,0 +1,60 @@
|
||||
package bio;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
|
||||
/**
|
||||
* @description: bio演示代码
|
||||
* @param
|
||||
* @return
|
||||
* @author lld
|
||||
*/
|
||||
public class SocketServer {
|
||||
|
||||
//1.0 服务端在处理完第一个客户端的所有事件之前,无法为其他客户端提供服务。
|
||||
//2.0 会产生大量空闲线程,浪费服务器资源。
|
||||
public static void main(String[] args) throws Exception {
|
||||
ServerSocket serverSocket = new ServerSocket(9001);
|
||||
while (true) {
|
||||
System.out.println("等待连接..");
|
||||
//阻塞方法
|
||||
Socket clientSocket = serverSocket.accept();
|
||||
System.out.println("有客户端连接了..");
|
||||
|
||||
// handler(clientSocket);
|
||||
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
handler(clientSocket);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
private static void handler(Socket clientSocket) throws Exception {
|
||||
// while (true){
|
||||
byte[] bytes = new byte[1024];
|
||||
System.out.println("准备read..");
|
||||
//接收客户端的数据,阻塞方法,没有数据可读时就阻塞
|
||||
int read = clientSocket.getInputStream().read(bytes);
|
||||
System.out.println("read完毕。。");
|
||||
if (read != -1) {
|
||||
// int i = (int) (1 + Math.random() * (10 - 1 + 1));
|
||||
// System.out.println("收到客户端: " + Thread.currentThread().getName() + "收到了数据开始休眠");
|
||||
// Thread.sleep(i*1000L);
|
||||
System.out.println("接收到客户端的数据:" + new String(bytes, 0, read));
|
||||
}
|
||||
// clientSocket.getOutputStream().write("HelloClient".getBytes());
|
||||
// clientSocket.getOutputStream().flush();
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package netty.base;
|
||||
|
||||
import netty.base.server.DiscardServer;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class Starter {
|
||||
public static void main(String[] args) throws Exception {
|
||||
new DiscardServer(9001).run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package netty.base.handler;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.util.CharsetUtil;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class DiscardServerHandler extends ChannelInboundHandlerAdapter {
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||
System.out.println("有客户端连接了");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
ByteBuf out = (ByteBuf) msg;
|
||||
String data = out.toString(CharsetUtil.UTF_8);
|
||||
System.out.println(data);
|
||||
short length = (short) data
|
||||
.getBytes().length;
|
||||
ByteBuf byteBuf = Unpooled.directBuffer(8);
|
||||
byteBuf.writeShort(length);
|
||||
byteBuf.writeBytes(data.getBytes());
|
||||
ctx.writeAndFlush(byteBuf);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package netty.base.server;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
|
||||
import netty.base.handler.DiscardServerHandler;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class DiscardServer {
|
||||
|
||||
private int port;
|
||||
|
||||
public DiscardServer(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
EventLoopGroup bossGroup = new NioEventLoopGroup(1); //线程池
|
||||
EventLoopGroup workerGroup = new NioEventLoopGroup();//
|
||||
|
||||
try {
|
||||
ServerBootstrap b = new ServerBootstrap(); // (2)
|
||||
b.group(bossGroup, workerGroup)
|
||||
.channel(NioServerSocketChannel.class) // (3)
|
||||
.childHandler(new ChannelInitializer<SocketChannel>() { // (4)
|
||||
@Override
|
||||
public void initChannel(SocketChannel ch) throws Exception {
|
||||
ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(
|
||||
1024,0,
|
||||
4,0,4
|
||||
));
|
||||
// ch.pipeline().addLast(new LengthFieldPrepender(2));
|
||||
// ch.pipeline().addLast(new StringDecoder());
|
||||
// ch.pipeline().addLast(new StringEncoder());
|
||||
ch.pipeline().addLast(new DiscardServerHandler());
|
||||
}
|
||||
})
|
||||
.option(ChannelOption.SO_BACKLOG, 128) // (5)
|
||||
.childOption(ChannelOption.SO_KEEPALIVE, true); // (6)
|
||||
|
||||
// Bind and start to accept incoming connections.
|
||||
System.out.println("tcp start success");
|
||||
ChannelFuture f = b.bind(port).sync(); // (7)
|
||||
|
||||
|
||||
// Wait until the server socket is closed.
|
||||
// In this example, this does not happen, but you can do that to gracefully
|
||||
// shut down your server.
|
||||
f.channel().closeFuture().sync();
|
||||
} finally {
|
||||
workerGroup.shutdownGracefully();
|
||||
bossGroup.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package netty.bytebuf;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
||||
public class NettyByteBuf {
|
||||
public static void main(String[] args) {
|
||||
// 创建byteBuf对象,该对象内部包含一个字节数组byte[10]
|
||||
ByteBuf byteBuf = Unpooled.buffer(10);
|
||||
System.out.println("byteBuf=" + byteBuf);
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
byteBuf.writeByte(i);
|
||||
}
|
||||
System.out.println("byteBuf=" + byteBuf);
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
System.out.println(byteBuf.getByte(i));
|
||||
}
|
||||
System.out.println("byteBuf=" + byteBuf);
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
System.out.println(byteBuf.readByte());
|
||||
}
|
||||
System.out.println("byteBuf=" + byteBuf);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package netty.chat;
|
||||
|
||||
import netty.chat.server.DiscardServer;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class Starter {
|
||||
|
||||
// line
|
||||
// header
|
||||
// body
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new DiscardServer(9001).run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package netty.chat.handler;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class DiscardServerHandler extends ChannelInboundHandlerAdapter {
|
||||
|
||||
static Set<Channel> channelList = new HashSet<>();
|
||||
|
||||
// @Override
|
||||
// public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||
// //通知其他人 我上线了
|
||||
// channelList.forEach(e->{
|
||||
// e.writeAndFlush("[客户端]" + ctx.channel().remoteAddress() + "上线了");
|
||||
// });
|
||||
//
|
||||
// channelList.add(ctx.channel());
|
||||
// }
|
||||
|
||||
//网络调试助手 -> 服务端
|
||||
//?直接发送!?
|
||||
//网络调试助手 -> 操作系统 -> 网络 -> 对方操作系统 -> 9000找到对应进程(我们的服务端)
|
||||
//!字符串
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
|
||||
String message = (String) msg;
|
||||
// Charset gbk = Charset.forName("GBK");
|
||||
System.out.println("收到数据:" + message);
|
||||
// 分发给聊天室内的所有客户端
|
||||
// 通知其他人 我上线了
|
||||
channelList.forEach(e->{
|
||||
if(e == ctx.channel()){
|
||||
e.writeAndFlush("[自己] : " + message);
|
||||
}else{
|
||||
e.writeAndFlush("[客户端] " +ctx.channel().remoteAddress()+":" + message);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: channel 处于不活跃的时候会调用
|
||||
* @param
|
||||
* @return void
|
||||
* @author lld
|
||||
*/
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||
//通知其他客户端 我下线了
|
||||
channelList.remove(ctx.channel());
|
||||
//通知其他人 我上线了
|
||||
channelList.forEach(e->{
|
||||
e.writeAndFlush("[客户端]" + ctx.channel().remoteAddress() + "下线了");
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package netty.chat.server;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
|
||||
import io.netty.handler.codec.string.StringDecoder;
|
||||
import io.netty.handler.codec.string.StringEncoder;
|
||||
import netty.chat.handler.DiscardServerHandler;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class DiscardServer {
|
||||
|
||||
private int port;
|
||||
|
||||
public DiscardServer(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
EventLoopGroup bossGroup = new NioEventLoopGroup(1); //线程池
|
||||
EventLoopGroup workerGroup = new NioEventLoopGroup();//
|
||||
|
||||
try {
|
||||
ServerBootstrap b = new ServerBootstrap(); // (2)
|
||||
b.group(bossGroup, workerGroup)
|
||||
.channel(NioServerSocketChannel.class) // (3)
|
||||
.childHandler(new ChannelInitializer<SocketChannel>() { // (4)
|
||||
@Override
|
||||
public void initChannel(SocketChannel ch) throws Exception {
|
||||
Charset gbk = Charset.forName("utf-8");
|
||||
ch.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, Unpooled.copiedBuffer("_"
|
||||
.getBytes())));
|
||||
ch.pipeline().addLast("encoder", new StringEncoder(gbk));//out
|
||||
ch.pipeline().addLast("decoder", new StringDecoder(gbk));//in
|
||||
ch.pipeline().addLast(new DiscardServerHandler());
|
||||
}
|
||||
})
|
||||
.option(ChannelOption.SO_BACKLOG, 128) // (5)
|
||||
.childOption(ChannelOption.SO_KEEPALIVE, true); // (6)
|
||||
|
||||
// Bind and start to accept incoming connections.
|
||||
System.out.println("tcp start success");
|
||||
ChannelFuture f = b.bind(port).sync(); // (7)
|
||||
|
||||
|
||||
// Wait until the server socket is closed.
|
||||
// In this example, this does not happen, but you can do that to gracefully
|
||||
// shut down your server.
|
||||
f.channel().closeFuture().sync();
|
||||
} finally {
|
||||
workerGroup.shutdownGracefully();
|
||||
bossGroup.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package netty.heaetbeat;
|
||||
|
||||
import netty.heaetbeat.server.DiscardServer;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class Starter {
|
||||
|
||||
|
||||
//2
|
||||
|
||||
//
|
||||
|
||||
//0-2 + 1 = 3 ___3 //5
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new DiscardServer(9001).run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package netty.heaetbeat.handler;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.handler.timeout.IdleState;
|
||||
import io.netty.handler.timeout.IdleStateEvent;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class HeartbeatHandler extends ChannelInboundHandlerAdapter {
|
||||
|
||||
int readTimeOut = 0;
|
||||
|
||||
@Override
|
||||
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
|
||||
IdleStateEvent event = (IdleStateEvent) evt;
|
||||
|
||||
if(event.state() == IdleState.READER_IDLE){
|
||||
readTimeOut++;
|
||||
}
|
||||
|
||||
if(readTimeOut >= 3){
|
||||
System.out.println("超时超过3次,断开连接");
|
||||
ctx.close();
|
||||
}
|
||||
|
||||
// System.out.println("触发了:" + event.state() + "事件");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package netty.heaetbeat.server;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.handler.timeout.IdleStateHandler;
|
||||
import netty.heaetbeat.handler.HeartbeatHandler;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class DiscardServer {
|
||||
|
||||
private int port;
|
||||
|
||||
public DiscardServer(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
EventLoopGroup bossGroup = new NioEventLoopGroup(1); //线程池
|
||||
EventLoopGroup workerGroup = new NioEventLoopGroup();//
|
||||
|
||||
try {
|
||||
ServerBootstrap b = new ServerBootstrap(); // (2)
|
||||
b.group(bossGroup, workerGroup)
|
||||
.channel(NioServerSocketChannel.class) // (3)
|
||||
.childHandler(new ChannelInitializer<SocketChannel>() { // (4)
|
||||
@Override
|
||||
public void initChannel(SocketChannel ch) throws Exception {
|
||||
ch.pipeline().addLast(new IdleStateHandler(3,0,0));
|
||||
ch.pipeline().addLast(new HeartbeatHandler());
|
||||
}
|
||||
})
|
||||
.option(ChannelOption.SO_BACKLOG, 128) // (5)
|
||||
.childOption(ChannelOption.SO_KEEPALIVE, true); // (6)
|
||||
|
||||
// Bind and start to accept incoming connections.
|
||||
System.out.println("tcp start success");
|
||||
ChannelFuture f = b.bind(port).sync(); // (7)
|
||||
|
||||
|
||||
// Wait until the server socket is closed.
|
||||
// In this example, this does not happen, but you can do that to gracefully
|
||||
// shut down your server.
|
||||
f.channel().closeFuture().sync();
|
||||
} finally {
|
||||
workerGroup.shutdownGracefully();
|
||||
bossGroup.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
15
io-study-master/io-study/src/main/java/netty/my/Starter.java
Normal file
15
io-study-master/io-study/src/main/java/netty/my/Starter.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package netty.my;
|
||||
|
||||
import netty.my.server.DiscardServer;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class Starter {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new DiscardServer(9001).run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package netty.my.codec;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class MyDecodecer extends ByteToMessageDecoder {
|
||||
|
||||
|
||||
//数据长度 + 数据
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
|
||||
if(in.readableBytes() < 4){
|
||||
return;
|
||||
}
|
||||
//数据长度 4 + 10000 9999
|
||||
int i = in.readInt();
|
||||
if(in.readableBytes() < i){
|
||||
in.resetReaderIndex();
|
||||
return;
|
||||
}
|
||||
byte[] data = new byte[i];//10000
|
||||
in.readBytes(data);
|
||||
System.out.println(new String(data));
|
||||
in.markReaderIndex();//10004
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package netty.my.handler;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class DiscardServerHandler extends ChannelInboundHandlerAdapter {
|
||||
|
||||
static Set<Channel> channelList = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||
}
|
||||
|
||||
//网络调试助手 -> 服务端
|
||||
//?直接发送!?
|
||||
//网络调试助手 -> 操作系统 -> 网络 -> 对方操作系统 -> 9000找到对应进程(我们的服务端)
|
||||
//!字符串
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: channel 处于不活跃的时候会调用
|
||||
* @param
|
||||
* @return void
|
||||
* @author lld
|
||||
*/
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package netty.my.server;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import netty.my.codec.MyDecodecer;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class DiscardServer {
|
||||
|
||||
private int port;
|
||||
|
||||
public DiscardServer(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
EventLoopGroup bossGroup = new NioEventLoopGroup(1); //线程池
|
||||
EventLoopGroup workerGroup = new NioEventLoopGroup();//
|
||||
|
||||
try {
|
||||
ServerBootstrap b = new ServerBootstrap(); // (2)
|
||||
b.group(bossGroup, workerGroup)
|
||||
.channel(NioServerSocketChannel.class) // (3)
|
||||
.childHandler(new ChannelInitializer<SocketChannel>() { // (4)
|
||||
@Override
|
||||
public void initChannel(SocketChannel ch) throws Exception {
|
||||
Charset gbk = Charset.forName("utf-8");
|
||||
ch.pipeline().addLast(new MyDecodecer());
|
||||
// ch.pipeline().addLast(new DiscardServerHandler());
|
||||
}
|
||||
})
|
||||
.option(ChannelOption.SO_BACKLOG, 128) // (5)
|
||||
.childOption(ChannelOption.SO_KEEPALIVE, true); // (6)
|
||||
|
||||
// Bind and start to accept incoming connections.
|
||||
System.out.println("tcp start success");
|
||||
ChannelFuture f = b.bind(port).sync(); // (7)
|
||||
|
||||
|
||||
// Wait until the server socket is closed.
|
||||
// In this example, this does not happen, but you can do that to gracefully
|
||||
// shut down your server.
|
||||
f.channel().closeFuture().sync();
|
||||
} finally {
|
||||
workerGroup.shutdownGracefully();
|
||||
bossGroup.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package netty.upload;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Data
|
||||
public class FileDto {
|
||||
|
||||
private String fileName; //文件名称
|
||||
|
||||
private Integer command; // 1请求创建文件 2传输文件
|
||||
|
||||
private byte[] bytes; //文件字节;再实际应用中可以使用非对称加密,以保证传输信息安全
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package netty.upload;
|
||||
|
||||
|
||||
import netty.upload.server.UploadFileServer;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class Starter {
|
||||
|
||||
//请求上传
|
||||
//创建文件
|
||||
//将客户端数据写入本地磁盘
|
||||
//command 4 fileName 4 8
|
||||
|
||||
//请求上传 -> 是否能够上传 -> 上传(客户端) -》将客户端数据写入本地磁盘
|
||||
public static void main(String[] args) throws Exception {
|
||||
new UploadFileServer(9001).run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package netty.upload.codec;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import netty.upload.FileDto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class UploadFileDecodecer extends ByteToMessageDecoder {
|
||||
|
||||
|
||||
//请求上传
|
||||
//创建文件
|
||||
//将客户端数据写入本地磁盘
|
||||
//command 4 fileName 4 8
|
||||
//数据长度 + 数据
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
|
||||
if(in.readableBytes() < 8){
|
||||
return;
|
||||
}
|
||||
//command 4
|
||||
int command = in.readInt();
|
||||
|
||||
FileDto fileDto = new FileDto();
|
||||
|
||||
int fileNameLen = in.readInt();
|
||||
|
||||
if(in.readableBytes() < fileNameLen){
|
||||
in.resetReaderIndex();
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] data = new byte[fileNameLen];
|
||||
in.readBytes(data);
|
||||
String fileName = new String(data);
|
||||
fileDto.setCommand(command);
|
||||
fileDto.setFileName(fileName);
|
||||
|
||||
if(command == 2){
|
||||
int dataLen = in.readInt();
|
||||
if(in.readableBytes() < dataLen){
|
||||
in.resetReaderIndex();
|
||||
return;
|
||||
}
|
||||
byte[] fileData = new byte[dataLen];
|
||||
in.readBytes(fileData);
|
||||
fileDto.setBytes(fileData);
|
||||
}
|
||||
in.markReaderIndex();//10004
|
||||
out.add(fileDto);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package netty.upload.handler;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import netty.upload.FileDto;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class UploadFileHandler extends ChannelInboundHandlerAdapter {
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
if(msg instanceof FileDto){
|
||||
FileDto dto = (FileDto) msg;
|
||||
if(dto.getCommand() == 1){
|
||||
//创建文件
|
||||
File file = new File("C://"+dto.getFileName());
|
||||
if(!file.exists()){
|
||||
file.createNewFile();
|
||||
}
|
||||
}else if(dto.getCommand() == 2){
|
||||
//写入文件
|
||||
save2File("C://"+dto.getFileName(),dto.getBytes());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static boolean save2File(String fname, byte[] msg){
|
||||
OutputStream fos = null;
|
||||
try{
|
||||
File file = new File(fname);
|
||||
File parent = file.getParentFile();
|
||||
boolean bool;
|
||||
if ((!parent.exists()) &
|
||||
(!parent.mkdirs())) {
|
||||
return false;
|
||||
}
|
||||
fos = new FileOutputStream(file,true);
|
||||
fos.write(msg);
|
||||
fos.flush();
|
||||
return true;
|
||||
}catch (FileNotFoundException e){
|
||||
return false;
|
||||
}catch (IOException e){
|
||||
File parent;
|
||||
return false;
|
||||
}
|
||||
finally{
|
||||
if (fos != null) {
|
||||
try{
|
||||
fos.close();
|
||||
}catch (IOException e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package netty.upload.server;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import netty.upload.codec.UploadFileDecodecer;
|
||||
import netty.upload.handler.UploadFileHandler;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: lld
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class UploadFileServer {
|
||||
|
||||
private int port;
|
||||
|
||||
public UploadFileServer(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
EventLoopGroup bossGroup = new NioEventLoopGroup(1); //线程池
|
||||
EventLoopGroup workerGroup = new NioEventLoopGroup();//
|
||||
|
||||
try {
|
||||
ServerBootstrap b = new ServerBootstrap(); // (2)
|
||||
b.group(bossGroup, workerGroup)
|
||||
.channel(NioServerSocketChannel.class) // (3)
|
||||
.childHandler(new ChannelInitializer<SocketChannel>() { // (4)
|
||||
@Override
|
||||
public void initChannel(SocketChannel ch) throws Exception {
|
||||
ch.pipeline().addLast(new UploadFileDecodecer());
|
||||
ch.pipeline().addLast(new UploadFileHandler());
|
||||
}
|
||||
})
|
||||
.option(ChannelOption.SO_BACKLOG, 128) // (5)
|
||||
.childOption(ChannelOption.SO_KEEPALIVE, true); // (6)
|
||||
|
||||
// Bind and start to accept incoming connections.
|
||||
System.out.println("tcp start success");
|
||||
ChannelFuture f = b.bind(port).sync(); // (7)
|
||||
|
||||
|
||||
// Wait until the server socket is closed.
|
||||
// In this example, this does not happen, but you can do that to gracefully
|
||||
// shut down your server.
|
||||
f.channel().closeFuture().sync();
|
||||
} finally {
|
||||
workerGroup.shutdownGracefully();
|
||||
bossGroup.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package nio;
|
||||
|
||||
import java.io.IOException;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @description: nio Selector演示代码
|
||||
* @param
|
||||
* @return
|
||||
* @author lld
|
||||
*/
|
||||
public class NioSelectorServer {
|
||||
|
||||
//BIO
|
||||
//1.0
|
||||
// 2 2 1 1 1 1
|
||||
// 0
|
||||
// 1 1 2 1 1 1
|
||||
// 0 0 0 0 0 0
|
||||
|
||||
//NIO
|
||||
//1.0
|
||||
// 2 2 2 2 2 2
|
||||
// 0
|
||||
//2.0
|
||||
// 2 2 2 2 2 2
|
||||
// 0
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
||||
int OP_ACCEPT = 1 << 4;
|
||||
System.out.println(OP_ACCEPT);
|
||||
|
||||
// 创建NIO ServerSocketChannel
|
||||
ServerSocketChannel serverSocket = ServerSocketChannel.open();
|
||||
serverSocket.socket().bind(new InetSocketAddress(9001));
|
||||
// 设置ServerSocketChannel为非阻塞
|
||||
serverSocket.configureBlocking(false);
|
||||
// 打开Selector处理Channel,即创建epoll
|
||||
Selector selector = Selector.open();
|
||||
// 把ServerSocketChannel注册到selector上,并且selector对客户端accept连接操作感兴趣
|
||||
SelectionKey selectionKey = serverSocket.register(selector, SelectionKey.OP_ACCEPT);
|
||||
System.out.println("服务启动成功");
|
||||
|
||||
while (true) {
|
||||
// 阻塞等待需要处理的事件发生 已注册事件发生后,会执行后面逻辑
|
||||
selector.select();
|
||||
|
||||
// 获取selector中注册的全部事件的 SelectionKey 实例
|
||||
Set<SelectionKey> selectionKeys = selector.selectedKeys();
|
||||
Iterator<SelectionKey> iterator = selectionKeys.iterator();
|
||||
|
||||
// 遍历SelectionKey对事件进行处理
|
||||
while (iterator.hasNext()) {
|
||||
SelectionKey key = iterator.next();
|
||||
// 如果是OP_ACCEPT事件,则进行连接获取和事件注册
|
||||
if (key.isAcceptable()) {
|
||||
ServerSocketChannel server = (ServerSocketChannel) key.channel();
|
||||
SocketChannel socketChannel = server.accept();
|
||||
socketChannel.configureBlocking(false);
|
||||
// 这里只注册了读事件,如果需要给客户端发送数据可以注册写事件
|
||||
SelectionKey selKey = socketChannel.register(selector, SelectionKey.OP_READ);
|
||||
System.out.println("客户端连接成功");
|
||||
} else if (key.isReadable()) { // 如果是OP_READ事件,则进行读取和打印
|
||||
SocketChannel socketChannel = (SocketChannel) key.channel();
|
||||
ByteBuffer byteBuffer = ByteBuffer.allocate(128);
|
||||
int len = socketChannel.read(byteBuffer);
|
||||
// 如果有数据,把数据打印出来
|
||||
if (len > 0) {
|
||||
System.out.println(Thread.currentThread().getName() + "接收到消息:" + new String(byteBuffer.array()));
|
||||
} else if (len == -1) { // 如果客户端断开连接,关闭Socket
|
||||
System.out.println("客户端断开连接");
|
||||
socketChannel.close();
|
||||
}
|
||||
}
|
||||
//从事件集合里删除本次处理的key,防止下次select重复处理
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
63
io-study-master/io-study/src/main/java/nio/NioServer.java
Normal file
63
io-study-master/io-study/src/main/java/nio/NioServer.java
Normal file
@@ -0,0 +1,63 @@
|
||||
package nio;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description: nio演示代码
|
||||
* @param
|
||||
* @return
|
||||
* @author lld
|
||||
*/
|
||||
public class NioServer {
|
||||
|
||||
// 保存客户端连接
|
||||
static List<SocketChannel> channelList = new ArrayList<>();
|
||||
|
||||
//10w
|
||||
//1w
|
||||
//
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
||||
// 创建NIO ServerSocketChannel,与BIO的serverSocket类似
|
||||
ServerSocketChannel serverSocket = ServerSocketChannel.open();
|
||||
serverSocket.socket().bind(new InetSocketAddress(9001));
|
||||
// 设置ServerSocketChannel为非阻塞
|
||||
serverSocket.configureBlocking(false);
|
||||
System.out.println("服务启动成功");
|
||||
|
||||
while (true) {
|
||||
// 非阻塞模式accept方法不会阻塞,否则会阻塞
|
||||
// NIO的非阻塞是由操作系统内部实现的,底层调用了linux内核的accept函数
|
||||
SocketChannel socketChannel = serverSocket.accept();
|
||||
if (socketChannel != null) { // 如果有客户端进行连接
|
||||
System.out.println("连接成功");
|
||||
// 设置SocketChannel为非阻塞
|
||||
socketChannel.configureBlocking(false);
|
||||
// 保存客户端连接在List中
|
||||
channelList.add(socketChannel);
|
||||
}
|
||||
// 遍历连接进行数据读取 10w - 1000 读写事件
|
||||
Iterator<SocketChannel> iterator = channelList.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
SocketChannel sc = iterator.next();
|
||||
ByteBuffer byteBuffer = ByteBuffer.allocate(128);
|
||||
// 非阻塞模式read方法不会阻塞,否则会阻塞
|
||||
int len = sc.read(byteBuffer);
|
||||
// 如果有数据,把数据打印出来
|
||||
if (len > 0) {
|
||||
System.out.println(Thread.currentThread().getName() + " 接收到消息:" + new String(byteBuffer.array()));
|
||||
} else if (len == -1) { // 如果客户端断开,把socket从集合中去掉
|
||||
iterator.remove();
|
||||
System.out.println("客户端断开连接");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
14
io-study-master/io-study/src/main/resources/mulitSend.py
Normal file
14
io-study-master/io-study/src/main/resources/mulitSend.py
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
import socket
|
||||
|
||||
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
|
||||
s.connect(("127.0.0.1",9001))
|
||||
|
||||
for i in range(100):
|
||||
print(i)
|
||||
string = "hello1哈_";
|
||||
body = bytes(string, 'utf-8')
|
||||
s.sendall(body)
|
||||
|
||||
|
||||
|
||||
21
io-study-master/io-study/src/main/resources/mycodecer.py
Normal file
21
io-study-master/io-study/src/main/resources/mycodecer.py
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
import uuid
|
||||
import socket
|
||||
|
||||
|
||||
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
|
||||
s.connect(("127.0.0.1",9001))
|
||||
data = "哈哈哈asdasdadfasdfasdfa哈123"
|
||||
print(data)
|
||||
dataBytes = bytes(data,"utf-8")
|
||||
dataLen = len(dataBytes)
|
||||
|
||||
data_len = dataLen.to_bytes(4, byteorder='big')
|
||||
# s.sendall(data_len + dataBytes)
|
||||
|
||||
for i in range(100):
|
||||
print(i)
|
||||
s.sendall(data_len + dataBytes)
|
||||
|
||||
|
||||
|
||||
34
io-study-master/io-study/src/main/resources/uploadFile.py
Normal file
34
io-study-master/io-study/src/main/resources/uploadFile.py
Normal file
@@ -0,0 +1,34 @@
|
||||
#-*- coding: UTF-8 -*-
|
||||
import socket,os,struct
|
||||
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
|
||||
s.connect(("127.0.0.1",9001))
|
||||
|
||||
filepath = "D://natapp.zip"
|
||||
if os.path.isfile(filepath):
|
||||
|
||||
filename = os.path.basename(filepath).encode('utf-8')
|
||||
|
||||
# 请求传输文件
|
||||
command = 1
|
||||
|
||||
body_len = len(filename)
|
||||
fileNameData = bytes(filename)
|
||||
i = body_len.to_bytes(4, byteorder='big')
|
||||
c = command.to_bytes(4, byteorder='big')
|
||||
|
||||
s.sendall(c + i + fileNameData)
|
||||
|
||||
fo = open(filepath,'rb')
|
||||
while True:
|
||||
command = 2;
|
||||
c = command.to_bytes(4, byteorder='big')
|
||||
filedata = fo.read(1024)
|
||||
print(len(filedata))
|
||||
b = len(filedata).to_bytes(4, byteorder='big')
|
||||
if not filedata:
|
||||
break
|
||||
s.sendall(c + i + fileNameData + b + filedata)
|
||||
fo.close()
|
||||
#s.close()
|
||||
else:
|
||||
print(False)
|
||||
Reference in New Issue
Block a user