软件通信七层结构(osi模型)中由协议套协议最终组成最高级应用层协议(http等等),下三层结构偏向与数据通信,上三层更偏向于数据处理,中间的传输层则是连接上三层与下三层之间的桥梁,每一层都做不同的工作,上层协议依赖与下层协议。
七层结构的最主要功能就是帮助不同系统的主机在不同的网络中进行数据传输。
数据传输层:tcp、udp协议,tcp协议依赖互联网协议(ip层协议)。
socket在第五层会话层,它并不是一个协议,而是一组接口(api),更是一个规范,为了方便使用底层协议而存在的一种抽象层。
websocket,http 等协议都是应用层协议(更面向于用户),依赖于传输层tcp协议。
websocket 在进行通信时,使用了http进行一次握手,数据传输使用tcp通道传输。
socket更像是一种网络编程的概念,是抽象出来的。
tcpSocket 与 websocket 的区别:
tcpSocket是tcp的协议传输,直接进行tcp的三次握手:client向server发送请求报文,server回复ack报文并分配资源,client发送报文并分配资源,连接建立。
websocket是基于tcp的应用层协议,采用一次HTTP握手。其发送的请求报文和socket是有区别的。
本片文章目的:
使用netty同端口监听tcpsocket和websocket消息传输。
实现思想:
在netty编程中,对于不同的消息肯定需要不同的编解码来处理,所以我们需要利用netty具有动态增删处理器handle的功能。
而从上文中我们知道websocket第一次是采用http握手的,因此debug握手请求,知道他的请求头部是GET方式。
所以我们需要根据这点来判断接收的消息是websocket还是tcpsocket。
1.判断handle如下:
/**
* 协议初始化解码器.
*
* 用来判定实际使用什么协议.</b>
*
*/
public class SocketChooseHandle extends ByteToMessageDecoder {
/** 默认暗号长度为23 */
private static final int MAX_LENGTH = 23;
/** WebSocket握手的协议前缀 */
private static final String WEBSOCKET_PREFIX = "GET /";
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
String protocol = getBufStart(in);
if (protocol.startsWith(WEBSOCKET_PREFIX)) {
SpringApplicationContextHolder.getSpringBeanForClass(PipelineAdd.class).websocketAdd(ctx);
ctx.pipeline().remove(LengthFieldBasedFrameDecoder.class);
ctx.pipeline().remove(LengthFieldPrepender.class);
ctx.pipeline().remove(BytebufToByteHandle.class);
}
in.resetReaderIndex();
ctx.pipeline().remove(this.getClass());
}
private String getBufStart(ByteBuf in){
int length = in.readableBytes();
if (length > MAX_LENGTH) {
length = MAX_LENGTH;
}
// 标记读位置
in.markReaderIndex();
byte[] content = new byte[length];
in.readBytes(content);
return new String(content);
}
}