文档章节

SQL server jdbc之prelogin数据包

harris2016
 harris2016
发布于 2016/07/08 15:06
字数 847
阅读 48
收藏 0

  为了做sql server的监控功能,需要了解SQL SERVER jdbc与SQL SERVER之间的通信协议。目前在Windows上面安装了sqlserver2016的developer版本。并且通过jdbc来操作数据库,可以得到jdbc的日志情况。通过日志可以了解到通信的过程,从通信的过程可以看到jdbc先发送了一个prelogin数据包到服务端。下面通过反编译的jdbc代码来学习prelogin包的内容。

prelogin数据包是在SQLServerConnection.class文件的Prelogin函数中进行构建的。与prelogin数据包相关的内容如下所示:

byte[] arrayOfByte1 = { 18, 1, 0, 67, 0, 0, 0, 0, 0, 0, 16, 0, 6, 1, 0, 22, 0, 1, 5, 0, 23, 0, 36, -1, 0, 0, 0, 0, 0, 0, this.requestedEncryptionLevel, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
......
ActivityId localActivityId = ActivityCorrelator.getNext();
byte[] arrayOfByte3 = Util.asGuidByteArray(localActivityId.getId());
byte[] arrayOfByte4 = Util.asGuidByteArray(this.clientConnectionId);
int i = arrayOfByte1.length - 36;

System.arraycopy(arrayOfByte4, 0, arrayOfByte1, i, arrayOfByte4.length);
i += arrayOfByte4.length;

System.arraycopy(arrayOfByte3, 0, arrayOfByte1, i, arrayOfByte3.length);
i += arrayOfByte3.length;
long l = localActivityId.getSequence();
Util.writeInt((int)l, arrayOfByte1, i);
i += 4;
......
try
{
  this.tdsChannel.write(arrayOfByte1, 0, arrayOfByte1.length);
  this.tdsChannel.flush();
}
......

上面去掉了无关代码后,其中arrayOfByte1数组中的内容为prelogin数据包的初始内容。再在初始内容的基础上面通过初步计算得到结果需要发送的数据包内容,修改的数据过程如下所示:

1. 把clientConnectionId的内容复制到arrayOfByte1数组中

2. 把localActivityId的id内容复制到arrayOfByte1数组中

3.把localActivityId的Sequence写到arrayOfByte1数组中,Sequence的长度为4个字节。

通过上面的修改后,把arrayOfByte1中的内容通过tdsChannel的write函数发送出去。

现在需要弄清楚的是requestedEncryptionLevel,clientConnectionId,localActivityId.id, localActivityId.Sequence值得来源或者计算过程。

1. requestedEncryptionLevel

这个参数的赋值是在SQLServerConnection.java文件的connect函数中,具体代码如下所示:

str2 = SQLServerDriverBooleanProperty.ENCRYPT.toString();               
str3 = this.activeConnectionProperties.getProperty(str2);               
if (str3 == null)                                                       
{                                                                       
  str3 = Boolean.toString(SQLServerDriverBooleanProperty.ENCRYPT.getDefa
  this.activeConnectionProperties.setProperty(str2, str3);              
}                                                                       
                                                                        
this.requestedEncryptionLevel = (booleanPropertyOn(str2, str3) ? 1 : 0);

str2的值为encrypt,str3的值是根据参数进行取值,默认情况下是false。于是可以得到当连接参数中没有设置encrypt时,requestedEncryptionLevel的值为0.否则为1.

2. clientConnectionId

这个参数的赋值是在SQLServerConnection.java文件的connectHelper函数中,具体代码如下所示:

this.clientConnectionId = UUID.randomUUID(); 
assert (null != this.clientConnectionId);    

clientConnectionId是通过UUID.randomUUID函数包装的。我机器上面jdbc打印出来的ID为ClientConnectionId: c4000772-d238-4feb-a388-fa63320b03e7。

3. localActivityId.id

从ActivityId.java文件中可以看到id也是一个UUID。取值的方法也是通过调用UUID.randomUUID函数来获得。具体的代码如下所示:

ActivityId()
{
  this.Id = UUID.randomUUID();
  this.Sequence = 0L;
  this.isSentToServer = false;
}

id是在ActivityId的构造函数中进行初始化的。

4. localActivityId.Sequence

Sequence的值是通过+1来计算的。计算的函数如下所示:

void Increment()
{
  if (this.Sequence < 4294967295L)
  {
    this.Sequence += 1L;
  }
  else
  {
    this.Sequence = 0L;
  }
  
  this.isSentToServer = false;
}

Sequence的长度是long型,所以长度不能超过4字节(FFFFFFFF)。

故通过上面的计算后能够得到prelogin的最终数据包格式是:

12 01 00 43 00 00 00 00 00 00 10 00 06 01 00 16   ...C............
00 01 05 00 17 00 24 FF 00 00 00 00 00 00 00 72   ......$........r
07 00 C4 38 D2 EB 4F A3 88 FA 63 32 0B 03 E7 C4   ...8..O...c2....
7D 75 88 A5 79 E5 4F B2 D7 23 35 0E A9 2B DB 01   }u..y.O..#5..+..
00 00 00  

这个数据包的内容是来做jdbc的连接日志,是最终的结果。

© 著作权归作者所有

harris2016
粉丝 10
博文 54
码字总数 30661
作品 0
杭州
程序员
私信 提问
Android———利用JDBC连接服务器数据库

1、Android平台下与服务器数据库通信的方法 在Android平台下,连接电脑服务器的MySQL、PostgreSQL、Oracle、Sybase、Microsoft SQLServer等数据库管理系统DBMS(database management system),...

xiahuawuyu
2012/10/10
1K
1
快速开发平台 WebBuilder JNDI配置

关于WebBuilder:http://www.oschina.net/p/webbuilder JNDI数据源配置:以Tomcat和SQL Server为例配置JNDI。 1、在应用目录下新建META-INF目录,并在该目录下新建context.xml文件; 2、编辑...

chenjiewb
2013/09/25
1K
1
求助...! 请求帮助。jdbc连接sqlserver 2008 出现错误

又出了一个问题 希望大家帮帮忙谢谢! 错误如下 com.microsoft.sqlserver.jdbc.SQLServerException: 通过端口 1433 连接到主机 localhost 的 TCP/IP 连接失败。错误:“驱动程序收到意外的登录...

刘轩麟
2014/03/20
1K
0
Linux下java利用jdbc链接mysql数据库和postgresql

亲测实例 把jdbc的jar包放到/usr/java/jdk1.6.0_41/jre/lib/ext下面才行 例子 java hello 10.100.145.161 sugdas_owner import java.sql.*; public class hello { public static void main(S......

紫地瓜
2015/03/17
154
0
微软宣布 SQL Server 2019 免费支持 Java

在 2018 年 9 月的时候,微软就宣布与领先的 Java 开源贡献者和发行商 Azul Systems 建立新的合作伙伴关系。这一伙伴关系允许所有 Azure 客户在微软和 Azul 联合提供的支持下,免费使用 Azul...

afterer
07/26
11.5K
26

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周六乱弹 —— 早上儿子问我他是怎么来的

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @凉小生 :#今日歌曲推荐# 少点戾气,愿你和这个世界温柔以待。中岛美嘉的单曲《僕が死のうと思ったのは (曾经我也想过一了百了)》 《僕が死の...

小小编辑
今天
1K
12
Excption与Error包结构,OOM 你遇到过哪些情况,SOF 你遇到过哪些情况

Throwable 是 Java 中所有错误与异常的超类,Throwable 包含两个子类,Error 与 Exception 。用于指示发生了异常情况。 Java 抛出的 Throwable 可以分成三种类型。 被检查异常(checked Exc...

Garphy
今天
38
0
计算机实现原理专题--二进制减法器(二)

在计算机实现原理专题--二进制减法器(一)中说明了基本原理,现准备说明如何来实现。 首先第一步255-b运算相当于对b进行按位取反,因此可将8个非门组成如下图的形式: 由于每次做减法时,我...

FAT_mt
昨天
40
0
好程序员大数据学习路线分享函数+map映射+元祖

好程序员大数据学习路线分享函数+map映射+元祖,大数据各个平台上的语言实现 hadoop 由java实现,2003年至今,三大块:数据处理,数据存储,数据计算 存储: hbase --> 数据成表 处理: hive --> 数...

好程序员官方
昨天
61
0
tabel 中含有复选框的列 数据理解

1、el-ui中实现某一列为复选框 实现多选非常简单: 手动添加一个el-table-column,设type属性为selction即可; 2、@selection-change事件:选项发生勾选状态变化时触发该事件 <el-table @sel...

everthing
昨天
20
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部