Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
GreyZeng
hello-netty
提交
8f81fac8
H
hello-netty
项目概览
GreyZeng
/
hello-netty
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
H
hello-netty
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
8f81fac8
编写于
9月 15, 2022
作者:
GreyZeng
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add client
上级
87db7c87
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
159 addition
and
4 deletion
+159
-4
pom.xml
pom.xml
+8
-4
src/main/java/chat/client/ClientHandler.java
src/main/java/chat/client/ClientHandler.java
+52
-0
src/main/java/chat/client/NettyClient.java
src/main/java/chat/client/NettyClient.java
+99
-0
未找到文件。
pom.xml
浏览文件 @
8f81fac8
...
...
@@ -15,29 +15,33 @@
<java.version>
17
</java.version>
<maven.compiler.source>
${java.version}
</maven.compiler.source>
<maven.compiler.target>
${java.version}
</maven.compiler.target>
<junit.version>
4.13.2
</junit.version>
<lombok.version>
1.18.24
</lombok.version>
<gson.version>
2.9.1
</gson.version>
<netty.version>
4.1.82.Final
</netty.version>
</properties>
<dependencies>
<dependency>
<groupId>
junit
</groupId>
<artifactId>
junit
</artifactId>
<version>
4.13.2
</version>
<version>
${junit.version}
</version>
</dependency>
<dependency>
<groupId>
org.projectlombok
</groupId>
<artifactId>
lombok
</artifactId>
<version>
1.18.24
</version>
<version>
${lombok.version}
</version>
<scope>
provided
</scope>
</dependency>
<dependency>
<groupId>
com.google.code.gson
</groupId>
<artifactId>
gson
</artifactId>
<version>
2.9.1
</version>
<version>
${gson.version}
</version>
</dependency>
<dependency>
<groupId>
io.netty
</groupId>
<artifactId>
netty-all
</artifactId>
<version>
4.1.82.Final
</version>
<version>
${netty.version}
</version>
</dependency>
</dependencies>
...
...
src/main/java/chat/client/ClientHandler.java
0 → 100644
浏览文件 @
8f81fac8
package
chat.client
;
import
io.netty.channel.ChannelHandlerContext
;
import
io.netty.channel.ChannelInboundHandlerAdapter
;
import
io.netty.buffer.ByteBuf
;
import
io.netty.channel.ChannelHandlerContext
;
import
io.netty.channel.ChannelInboundHandlerAdapter
;
import
java.util.Date
;
import
java.util.UUID
;
import
java.util.Date
;
/**
* @author <a href="mailto:410486047@qq.com">Grey</a>
* @date 2022/9/15
* @since
*/
public
class
ClientHandler
extends
ChannelInboundHandlerAdapter
{
@Override
public
void
channelActive
(
ChannelHandlerContext
ctx
)
throws
Exception
{
System
.
out
.
println
(
new
Date
()
+
": 客户端开始登录"
);
// 创建登录对象
LoginRequestPacket
loginRequestPacket
=
new
LoginRequestPacket
();
loginRequestPacket
.
setUserId
(
UUID
.
randomUUID
().
toString
());
loginRequestPacket
.
setUsername
(
"flash"
);
loginRequestPacket
.
setPassword
(
"pwd"
);
// 编码
ByteBuf
buffer
=
PacketCodeC
.
INSTANCE
.
encode
(
ctx
.
alloc
(),
loginRequestPacket
);
// 写数据
ctx
.
channel
().
writeAndFlush
(
buffer
);
}
@Override
public
void
channelRead
(
ChannelHandlerContext
ctx
,
Object
msg
)
{
ByteBuf
byteBuf
=
(
ByteBuf
)
msg
;
Packet
packet
=
PacketCodeC
.
INSTANCE
.
decode
(
byteBuf
);
if
(
packet
instanceof
LoginResponsePacket
)
{
LoginResponsePacket
loginResponsePacket
=
(
LoginResponsePacket
)
packet
;
if
(
loginResponsePacket
.
isSuccess
())
{
System
.
out
.
println
(
new
Date
()
+
": 客户端登录成功"
);
}
else
{
System
.
out
.
println
(
new
Date
()
+
": 客户端登录失败,原因:"
+
loginResponsePacket
.
getReason
());
}
}
}
}
src/main/java/chat/client/NettyClient.java
0 → 100644
浏览文件 @
8f81fac8
package
chat.client
;
import
io.netty.bootstrap.Bootstrap
;
import
io.netty.buffer.ByteBuf
;
import
io.netty.channel.Channel
;
import
io.netty.channel.ChannelHandlerContext
;
import
io.netty.channel.ChannelInboundHandlerAdapter
;
import
io.netty.channel.ChannelInitializer
;
import
io.netty.channel.ChannelOption
;
import
io.netty.channel.ChannelPipeline
;
import
io.netty.channel.nio.NioEventLoopGroup
;
import
io.netty.channel.socket.nio.NioSocketChannel
;
import
io.netty.util.AttributeKey
;
import
java.nio.charset.StandardCharsets
;
import
java.util.Date
;
import
java.util.concurrent.TimeUnit
;
/**
* Netty 可自动重连的客户端,增加了IO处理逻辑
*
* @author <a href="mailto:410486047@qq.com">Grey</a>
* @date 2022/9/12
* @since
*/
public
class
NettyClient
{
static
final
int
MAX_RETRY
=
6
;
static
final
String
HOST
=
"localhost"
;
static
final
int
PORT
=
8000
;
public
static
void
main
(
String
[]
args
)
throws
InterruptedException
{
Bootstrap
bootstrap
=
new
Bootstrap
();
NioEventLoopGroup
group
=
new
NioEventLoopGroup
();
bootstrap
// 指定线程模型
.
group
(
group
)
// 指定IO类型为NIO
.
channel
(
NioSocketChannel
.
class
)
// attr可以为客户端Channel绑定自定义属性
.
attr
(
AttributeKey
.
newInstance
(
"clientName"
),
"nettyClient"
)
// 连接的超时时间,如果超过这个时间,仍未连接到服务端,则表示连接失败
.
option
(
ChannelOption
.
CONNECT_TIMEOUT_MILLIS
,
5000
)
// 表示是否开启TCP底层心跳机制,true表示开启
.
option
(
ChannelOption
.
SO_KEEPALIVE
,
true
)
// 是否开启Nagle算法,如果要求高实时性,有数据就马上发送,则为true
// 如果需要减少发送次数,减少网络交互,就设置为false
.
option
(
ChannelOption
.
TCP_NODELAY
,
true
)
// IO处理逻辑
.
handler
(
new
ChannelInitializer
<>()
{
@Override
protected
void
initChannel
(
Channel
ch
)
{
ch
.
pipeline
().
addLast
(
new
ChannelInboundHandlerAdapter
()
{
// 这个方法会在客户端连接建立成功之后被调用
@Override
public
void
channelActive
(
ChannelHandlerContext
ctx
)
{
System
.
out
.
println
(
new
Date
()
+
": 客户端写出数据"
);
// 包装成ByteBuf并发送到服务端
// 注:Netty中的数据是以 ByteBuf 为单位的。
ctx
.
channel
().
writeAndFlush
(
getByteBuf
(
ctx
));
}
@Override
public
void
channelRead
(
ChannelHandlerContext
ctx
,
Object
msg
)
{
ByteBuf
byteBuf
=
(
ByteBuf
)
msg
;
System
.
out
.
println
(
new
Date
()
+
": 客户端读取到的数据 -> "
+
byteBuf
.
toString
(
StandardCharsets
.
UTF_8
));
}
private
ByteBuf
getByteBuf
(
ChannelHandlerContext
ctx
)
{
ByteBuf
buffer
=
ctx
.
alloc
().
buffer
();
byte
[]
bytes
=
"hello world"
.
getBytes
(
StandardCharsets
.
UTF_8
);
buffer
.
writeBytes
(
bytes
);
return
buffer
;
}
})
}
});
connect
(
bootstrap
,
HOST
,
PORT
,
MAX_RETRY
);
}
private
static
void
connect
(
final
Bootstrap
bootstrap
,
final
String
host
,
final
int
port
,
int
retry
)
{
bootstrap
.
connect
(
host
,
port
).
addListener
(
future
->
{
if
(
future
.
isSuccess
())
{
System
.
out
.
println
(
"连接成功!"
);
}
else
if
(
retry
==
0
)
{
System
.
err
.
println
(
"重试次数已经使用完毕"
);
}
else
{
// 第几次重试
int
order
=
(
MAX_RETRY
-
retry
)
+
1
;
// 本次的重试间隔
int
delay
=
1
<<
order
;
System
.
out
.
println
(
new
Date
()
+
": 连接失败,第"
+
order
+
"次重连..."
);
bootstrap
.
config
().
group
().
schedule
(()
->
connect
(
bootstrap
,
host
,
port
,
retry
-
1
),
delay
,
TimeUnit
.
SECONDS
);
}
});
}
// TEST
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录