一、服务端
public class WebSocketChannelInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
//HttpServerCodec: 针对http协议进行编解码
pipeline.addLast("httpServerCodec", new HttpServerCodec());
//ChunkedWriteHandler分块写处理,文件过大会将内存撑爆
pipeline.addLast("chunkedWriteHandler", new ChunkedWriteHandler());
/**
* 作用是将一个Http的消息组装成一个完成的HttpRequest或者HttpResponse,那么具体的是什么
* 取决于是请求还是响应, 该Handler必须放在HttpServerCodec后的后面
*/
pipeline.addLast("httpObjectAggregator", new HttpObjectAggregator(8192));
//用于处理websocket, /ws为访问websocket时的uri
// pipeline.addLast("webSocketServerProtocolHandler", new WebSocketServerProtocolHandler("/ws"));
pipeline.addLast("myWebSocketHandler", new WebSocketHandler());
}
}
public class WebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
Channel channel = ctx.channel();
System.out.println("--来自客户端的消息:" + channel.remoteAddress() + ":" + msg.text());
ctx.channel().writeAndFlush(new TextWebSocketFrame("--来自服务端: " + LocalDateTime.now() + "-> sztao"));
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
System.out.println("--频道ID: " + ctx.channel().id().asLongText());
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
System.out.println("用户下线: " + ctx.channel().id().asLongText());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.channel().close();
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
Channel channel = ctx.channel();
boolean active = channel.isActive();
if (active) {
System.out.println("--与远程主机 [" + channel.remoteAddress() + "] 建立连接成功");
ctx.channel().writeAndFlush("--来自服务端: " + LocalDateTime.now() + "-> sztao");
}
}
}
public class WebsocketServer {
public static void main(String[] args) throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try{
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new WebSocketChannelInitializer());
ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();
channelFuture.channel().closeFuture().sync();
}finally{
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
二、web前端
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Socket</title>
<script type="text/javascript">
var websocket;
//如果浏览器支持WebSocket
if(window.WebSocket){
websocket = new WebSocket("ws://localhost:8899/ws"); //获得WebSocket对象
//当有消息过来的时候触发
websocket.onmessage = function(event){
var respMessage = document.getElementById("respMessage");
respMessage.value = respMessage.value + "\n" + event.data;
}
//连接关闭的时候触发
websocket.onclose = function(event){
var respMessage = document.getElementById("respMessage");
respMessage.value = respMessage.value + "\n断开连接";
}
//连接打开的时候触发
websocket.onopen = function(event){
var respMessage = document.getElementById("respMessage");
respMessage.value = "建立连接";
}
}else{
alert("浏览器不支持WebSocket");
}
function sendMsg(msg) { //发送消息
if(window.WebSocket){
if(websocket.readyState == WebSocket.OPEN) { //如果WebSocket是打开状态
websocket.send(msg); //send()发送消息
}
}else{
return;
}
}
</script>
</head>
<body>
<form onsubmit="return false">
<textarea style="width: 300px; height: 200px;" name="message"></textarea>
<input type="button" onclick="sendMsg(this.form.message.value)" value="发送"><br>
<h3>信息</h3>
<textarea style="width: 300px; height: 200px;" id="respMessage"></textarea>
<input type="button" value="清空" onclick="javascript:document.getElementById('respMessage').value = ''">
</form>
</body>
</html>
三、Java客户端
/**
*
*
*/
public class ClientHandler extends SimpleChannelInboundHandler<String> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String s) throws Exception {
//打印服务端的发送数据
System.out.println(s);
}
}
/**
*
*
*/
public class ClientIniterHandler extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
//注册管道
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
pipeline.addLast("http", new HttpClientCodec());
pipeline.addLast("chat", new ClientHandler());
}
}
/**
*
*
*/
public class NettyClient {
private String ip;
private int port;
private boolean stop = false;
public NettyClient(String ip, int port) {
this.ip = ip;
this.port = port;
}
public void run() throws IOException {
//设置一个多线程循环器
EventLoopGroup workerGroup = new NioEventLoopGroup();
//启动附注类
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(workerGroup);
//指定所使用的NIO传输channel
bootstrap.channel(NioSocketChannel.class);
//指定客户端初始化处理
bootstrap.handler(new ClientIniterHandler());
try {
//连接服务
Channel channel = bootstrap.connect(ip, port).sync().channel();
// Channel channel = bootstrap.connect(ip, port).sync().channel();
while (true) {
//向服务端发送内容
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String content = reader.readLine();
System.out.println("==" + content);
if (StringUtils.isNotEmpty(content)) {
if (StringUtils.equalsIgnoreCase(content, "q")) {
System.exit(1);
}
channel.writeAndFlush(new TextWebSocketFrame(content));
}
}
} catch (InterruptedException e) {
e.printStackTrace();
System.exit(1);
} finally {
workerGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
new NettyClient("127.0.0.1", 8899).run();
}
}