我能够将一条启动消息发送到我运行的PostgreSQL服务器并从该服务器获得响应。我得到了ParameterStatus消息。问题是我从来没有得到任何类型的身份验证消息。我的问题是:为什么服务器永远不会向我发送任何类型的身份验证消息?
下面我将向您展示我的代码片段,用于了解协议的启动部分如何工作,以及为调试输出的几行(希望您甚至不必阅读我的代码),我认为是来自PostgreSQL文档的有用信息,用于理解我的问题,以及我发现对可视化协议有用的另一个资源。
这是我的代码:
var net = require('net');
var BlueBird = require('bluebird');
var Buffer = require('buffer').Buffer;
var createStartupMessage = function(user_name, database_name){
var buffer_size = 22 + user_name.length + 1 + database_name.length + 1 + 1;
var StartUpMessage = new Buffer(buffer_size);
var position_in_buffer = 0;
StartUpMessage.writeUInt32BE(buffer_size, 0);
position_in_buffer += 4;
StartUpMessage.writeUInt32BE(196608, position_in_buffer); //version 3.0
position_in_buffer += 4;
position_in_buffer = addMessageSegment(StartUpMessage, "user", position_in_buffer);
position_in_buffer = addMessageSegment(StartUpMessage, user_name, position_in_buffer);
position_in_buffer = addMessageSegment(StartUpMessage, "database", position_in_buffer);
position_in_buffer = addMessageSegment(StartUpMessage, database_name, position_in_buffer);
//Add the last null terminator to the buffer
addNullTerminatorToMessageSegment(StartUpMessage, position_in_buffer);
console.log("The StartUpMessage looks like this in Hexcode: " + StartUpMessage.toString('hex'));
console.log("The length of the StartupMessage in Hexcode is: " + StartUpMessage.toString('hex').length);
return StartUpMessage;
};
var addMessageSegment = function(StartUpMessage, message_segment, position_in_buffer){
var bytes_in_message_segment = Buffer.byteLength(message_segment);
StartUpMessage.write(message_segment, position_in_buffer, StartUpMessage - position_in_buffer, 'utf8');
position_in_buffer = position_in_buffer + bytes_in_message_segment;
position_in_buffer = addNullTerminatorToMessageSegment(StartUpMessage, position_in_buffer);
return position_in_buffer;
};
var addNullTerminatorToMessageSegment = function(StartUpMessage, position_in_buffer){
StartUpMessage.writeUInt8(0, position_in_buffer);
position_in_buffer = position_in_buffer + 1;
return position_in_buffer;
};
//Here is where everything starts. The functions above are called within this BlueBird Promise.
BlueBird.coroutine(function* () {
var host = "127.0.0.1";
var port = "5432";
var idle_timeout = 10000;
var MySocket = new net.Socket();
MySocket.setTimeout(idle_timeout);
var StartUpMessage = createStartupMessage("testusertwo", "testdatabasetwo");
var data = yield new Promise(
function resolver(resolve, reject) {
var number_of_responses = 0;
var number_of_responses_to_wait_for = 2;
MySocket.on('connect', function () {
var message = StartUpMessage.toString("utf8");
var flushed = MySocket.write(message, "utf8");
console.log("Message flushed to kernel: " + flushed);
});
MySocket.on('data', function (data) {
console.log("The response from the server is: " + data.toString('utf8'));
console.log("----This Line Divides the Response Below from the Response Above----");
if( number_of_responses !== number_of_responses_to_wait_for){
number_of_responses += 1;
} else {
resolve(data);
}
});
MySocket.on('error', function (error) {
reject(error);
});
MySocket.connect(port, host);
}
);
return data;
})()
.then(function (data) {
return data;
})
.catch(function (error) {
console.error(error);
});
这些是我的代码输出用于调试目的的几行。它显示了我发送到服务器的初始utf-8编码消息的十六进制代码表示(启动消息格式通过底部的链接显示在幻灯片9上)。然后它显示服务器响应。
在此之后我的程序挂起等待我等待它发送一个Authentication类消息。在启动消息中,为方便起见,我将前两个32位Big Endian整数和所有空终止符加粗。还有,?最后的标记(在?M2 \ ?? ZI中)实际上是来自utf-8的那些钻石问号,并且这个结束部分也在每次运行时都会发生变化。我不知道为什么。
我的代码的一些输出:
StartUpMessage在Hexcode中显示如下:
**0000003300030000**75736572**00**746573747573657274776f**00**6461746162617365**00**74657374646174616261736574776f**0000**
服务器的响应是:
Sapplication_nameSclient_encodingUTF8SDateStyleISO,MDYSinteger_datetimesonSntervalStylepostgresSis_superuseroffSserver_encodingUTF8Sserver_version9.5.0S& session_authorizationtestusertwoS#standard_conforming_stringsonSTimeZoneUS / EasternK ?M2 \ ?? ZI
我认为这是Postgresql文档中的相关信息:
50.2.Message Flow.1。开始:
要开始会话,前端会打开与服务器的连接并发送启动消息。
验证周期以服务器拒绝连接尝试(ErrorResponse)或发送AuthenticationOk结束。
本节还说明其他一些内容,如果不需要密码并且一切都没有错误,我应该获得列出的许多身份验证消息之一(例如AuthenticationCleartextPassword消息)或AuthenticationOk。如果有错误,那么我应该收到ErrorResponse消息。
50.5.Message格式:
在本节中,指出如果服务器响应中的第一个字节为“S”,则将Message分类为ParameterStatus消息。
在本节中,它还指出,如果服务器响应中的第一个字节为“R”,则将消息归类为“身份验证”消息。
我找到了有用的资源:
我认为这是可视化消息流协议的非常好的资源。作者的名字是Jan Urban ski。在幻灯片9上,显示了启动数据包。我发现的唯一的东西(无论如何都是node.js)需要在之前有另一个空终止符框。 。 。框。
https://www.pgcon.org/2014/schedule/attachments/330_postgres-for-the-wire.pdf
答案 0 :(得分:0)
在查看Wireshark之后,我意识到我收到了一条身份验证消息('R'类型的消息)。问题是我正在从服务器中错误地解析数据。我立即将它转换为UTF8字符串。在将任何数据转换为UTF8之前,需要根据消息格式解析数据。这是因为格式不仅仅是一串串起来的字符。它们包括32位大端整数和16位大端整数。