Java Vertex NetServer控制读取流

Java Vertex NetServer控制读取流,java,tcp,vert.x,tcpserver,Java,Tcp,Vert.x,Tcpserver,我正试图模拟TCP服务器,以便基于我必须使用的现有基础设施,使用Vertx进行测试 我模拟的服务器工作完全异步,并且根据缓冲区中指示请求长度的pre头知道传入缓冲区的长度 我需要在连接到模拟TCP服务器的每个客户端套接字上读取传入请求的前6个字符。从这个预标题中,我读取了请求的实际长度(例如,对于xx3018,我知道请求的完整长度是3018) 然后,我需要根据长度读取缓冲区的其余部分,将其与响应映射匹配,并为请求返回正确的响应 使用纯java的工作模拟服务器示例(快速实现,因此不会阻止其他开发:

我正试图模拟TCP服务器,以便基于我必须使用的现有基础设施,使用Vertx进行测试

我模拟的服务器工作完全异步,并且根据缓冲区中指示请求长度的pre头知道传入缓冲区的长度

我需要在连接到模拟TCP服务器的每个客户端套接字上读取传入请求的前6个字符。从这个预标题中,我读取了请求的实际长度(例如,对于xx3018,我知道请求的完整长度是3018)

然后,我需要根据长度读取缓冲区的其余部分,将其与响应映射匹配,并为请求返回正确的响应

使用纯java的工作模拟服务器示例(快速实现,因此不会阻止其他开发:)


我似乎找不到一种方法来控制输入流,就像我用纯java控制输入流一样。

在很长一段时间不考虑这个问题后,我决定玩一下

我记得在不同的项目中使用了以下模块:

我还记得,在tcp网桥的内部协议中,它将有效负载的长度附加到通过tcp网桥发送的缓冲区中,我查看了源代码以了解它如何处理块(也称为帧)

我发现:这正是我想要实现的目标:)

我对它做了一些修改,转换成Kotlin,这样我就可以控制头的大小以及它提取有效负载长度的方式

下面是一个使用Vert.x NetServer控制读取流的粗略、快速和肮脏的示例:

suspend fun main(){
val vertx=vertx.vertx()
initServer(vertx)
initClient(vertx)
}
挂起initServer(vertx:vertx){
val server=vertx.createNetServer(netServerOptionsOf(port=8888,host=“localhost”))
服务器
.connectHandler{socket->
val parser=FrameParser(
headerSize=4,
车头装卸工={
it.getInt(0)
},
处理程序={
println(it.toString())
println(“--”)
}
)
socket.handler(解析器)
socket.exceptionHandler{
it.printStackTrace()
socket.close()
}
}
.listenAwait()
}
挂起客户端(vertx:vertx){
val client=vertx.createNetClient()
val socket=client.connectAwait(port=8888,host=“localhost”)
val message=“开始|${”foobarfoobar“。重复(100)}|结束”
val length=message.length
重复(5){
重复(100){
vertx.setPeriodic(10){
socket.write(
Buffer.Buffer()
.appendInt(长度)
.appendString(消息)
)
}
}
延迟(1000)
}
}
/**
*基于:https://github.com/vert-x3/vertx-tcp-eventbus-bridge/blob/master/src/main/java/io/vertx/ext/eventbus/bridge/tcp/impl/protocol/FrameParser.java
*/
类框架解析器(
私人val标题:Int,
私人val headerHandler:(缓冲)->Int,
私有val处理程序:(缓冲区)->单元
):处理程序{
私有变量_缓冲区:缓冲区?=null
私有变量_offset=0
覆盖有趣的句柄(缓冲区:缓冲区?){
附加(缓冲区)
变量偏移量:Int
while(true){
//设置倒带点。如果出现故障,
//请等待下一个句柄()/append(),然后重试
偏移量=\u偏移量
//缓冲区中有多少字节
val remainingBytes=字节剩余()
//至少预期的标头大小
如果(剩余字节数<标题大小){
打破
}
//信息的长度是多少
val length:Int=headerHandler(_buffer!!.getBuffer(_offset,_offset+headerSize))
_偏移量+=标题化
if(剩余字节数-标题大小>=长度){
//我们有一个完整的信息
处理程序(\u buffer!!.getBuffer(\u offset,\u offset+length))
_偏移量+=长度
}否则{
//数据不足:倒带,然后等待
//等待下一个数据包出现
_偏移量=偏移量
打破
}
}
}
私人娱乐附加(newBuffer:Buffer?){
if(newBuffer==null){
返回
}
//首轮
如果(_buffer==null){
_缓冲区=新缓冲区
返回
}
//数据不足
如果(\u偏移量>=\u缓冲区!!.length()){
_缓冲区=新缓冲区
_偏移量=0
返回
}
//超大包装
如果(_offset>0){
_buffer=\u buffer!!.getBuffer(\u offset,\u buffer!!.length())
}
_缓冲区!!.appendBuffer(新缓冲区)
_偏移量=0
}
private fun byteslaining():Int{
返回if(_buffer!!.length()-_offset<0){
0
}否则{
_缓冲区!!.length()-\u偏移量
}
}
}
public void run(String... args) throws Exception {
    log.info("Starting TCP Server");

    ServerSocket serverSocket = new ServerSocket(1750);

    while (true) {
        try {
            Socket socket = serverSocket.accept();

            CompletableFuture.runAsync(() -> {
                Exception e = null;
                while (e == null) {
                    try {
                        InputStream inputStream = socket.getInputStream();
                        OutputStream outputStream = socket.getOutputStream();

                        byte[] preHeader = new byte[6];
                        inputStream.read(preHeader);

                        String preHeaderValue = new String(preHeader);
                        log.info("Pre header: {}", preHeaderValue);

                        int length = Integer.valueOf(preHeaderValue.substring(2));
                        log.info("Request full length: {}", length);
                        byte[] request = new byte[length - 6];

                        inputStream.read(request);

                        String requestValue = new String(request);

                        log.info("Request: {}", requestValue);

                        String response = this.requestResponseProvider.getResponse(preHeaderValue + requestValue);
                        log.info("Response: {}", response);
                        outputStream.write(response.getBytes());
                    } catch (Exception ex) {
                        log.error("Encountered a problem: {}", e.getMessage());
                        e = ex;
                    }
                }
            });
        } catch (Exception e) {
            log.error("Encountered a problem: {}", e.getMessage());
        }
    }
}