第二章,Netty服务端与BIO客户端通信
基于上一章的内容,我们学习了如何在IDEA中创建并导入Netty框架,并简单实现了一个可以接收BIO客户端发送来的String数据的服务端Demo。今天来聊聊如何发送数据到BIO客户端。
上一章的链接在这里 https://blog.csdn.net/sinat_18538231/article/details/101175725
实现echo服务端
为了测试服务端发送消息给客户端,我们这里实现一个echo服务端来进行测试。
1.改造客户端
上一章中,我们的客户端仅仅实现了Socket连接服务器并发送一条测试数据,之后就断开连接。
这里我们对其进行改造,使其在发送完测试数据后,可以读取服务端发送回来的数据并打印在控制台。
public class Main {
public static void main(String[] args) {
try {
InetAddress addr;
Socket socket = new Socket("127.0.0.1", 8088);
addr = socket.getInetAddress();
System.out.println("连接到" + addr);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String lineString = "连接测试";
writer.write(lineString);
writer.flush();
// 下面是新增加的代码
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String input;
while (true){
input = reader.readLine();
System.out.println(input);
}
} catch (IOException e) {
System.out.println("无法连接");
}
}
}
可以看到,我们在是用writer.flush()将数据发送出去后,从socket获取到了输入流,然后从中循环读取服务端返回的数据。
2.改造服务端
在上一章中,我们的服务端做的事情就是,当客户端连接时,打印其ip和端口;当客户端发送数据时,我们将其解码并打印在控制台上。因此我们下面要做的就是将客户端传来的数据发送回去。
public class SocketServerHandler extends SimpleChannelInboundHandler<String> {
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, String s) throws Exception {
System.out.println("客户端发来:" + s);
String str = s + "\n"; // 加\n 使得可以通过readline读出来
ctx.writeAndFlush(str);
}
}
对于我们之前服务端的demo的改造,只需要对SocketServerHandler进行修改就行。
上一章我们讲到SocketServerHandler是对接收到的数据进行处理的类,而其中的channelRead0方法是数据处理的主体,因此我们这里仅仅修改该方法。
将客户端发来的数据加上"\n"后,调用ctx.writeAndFlush(str)发送回去。
这里加上\n的原因是我们客户端使用的是readLine方法,若是没读到\r或\n程序就不会返回数据,导致程序阻塞住。
3.运行测试
先启动服务端,再启动客户端,控制台分别得到如下打印输出。
服务端输出:
客户端输出:
这样就表示服务端发送数据到客户端成功。
至此我们已经完成了netty与原生bio的数据交互的功能,然而目前为止我们还是使用的单个String数据来进行数据交互。对于有众多功能协议需要处理的游戏服务器来说,这么做显然是效率低下且不足以满足业务需求的。
下一章我们将学习使用protobuf协议格式,并且将其应用到我们的demo中。