2016-02-27 64 views
1

我能夠將啓動消息發送到我正在運行的PostgreSQL服務器並從該服務器獲得響應。我得到ParameterStatus消息。問題是我從來沒有得到任何類型的認證信息。我的問題是:爲什麼服務器從不向我發送任何類型的身份驗證消息?如何使用node.js啓動PostgreSQL消息流協議net.Socket

下面我將向您展示我的代碼片斷,以瞭解協議的啓動部分是如何工作的,以及它爲調試輸出的幾行代碼(以便希望您甚至不必閱讀我的代碼),我認爲是來自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中)。然後顯示服務器響應。

在此之後,我的程序掛起等待,我等待看到它發送一個認證類的消息。在啓動消息中,爲了方便起見,我粗體顯示了前兩個32位Big Endian整數和所有空終止符。另外,最後的標記(在?M2 \ ?? ZI中)實際上是來自utf-8的那些鑽石問號,並且這個結尾部分也在每次運行中都改變。我不知道爲什麼。

從我的代碼的一些輸出:

的StartUpMessage看起來像這樣在十六進制編碼:

**0000003300030000**75736572**00**746573747573657274776f**00**6461746162617365**00**74657374646174616261736574776f**0000** 

來自服務器的響應是:

Sapplication_nameSclient_encodingUTF8SDateStyleISO,MDYSinteger_datetimesonSntervalStylepostgresSis_superuseroffSserver_encodingUTF8Sserver_version9.5.0S &會話?_authorizationtestusertwoS#standard_conforming_stringsonSTimeZoneUS/EasternK M2 \ ?? ZI

這是什麼,我認爲是從PostgreSQL文檔相關信息:

50.2.Message Flow.1.Start行動:

要開始會話,前端將打開與服務器的連接併發送啓動消息。

認證週期以服務器拒絕連接嘗試(ErrorResponse)或發送AuthenticationOk結束。

本節說一些其他的事情也使得它聽起來像我應該要麼得到上市(如AuthenticationCleartextPassword消息)的衆多身份驗證信息或AuthenticationOk之一,如果不需要密碼,一切都發生無錯誤。如果有錯誤,那麼我應該得到一個ErrorResponse消息。

50.5.Message格式:

在本節中是表示,如果在服務器響應的第一個字節是「S」,則該消息被分類爲ParameterStatus消息。

在本節中它也表明,如果在服務器響應的第一個字節是「R」,則該消息被分類爲認證消息。

有用的資源,我發現:

我認爲這是可視化的消息流協議非常好的資源。作者姓名是Jan Urban滑雪。在幻燈片9上,顯示啓動數據包。我發現的唯一的東西(無論如何都是node.js)是需要有一個null結束符框之前。 。 。框。

https://www.pgcon.org/2014/schedule/attachments/330_postgres-for-the-wire.pdf

回答

0

尋找上的Wireshark後,我意識到,我得到的認證消息( 'R' 類型消息)。問題在於我錯誤地解析了服務器中的數據。我立即將其轉換爲UTF8字符串。數據需要在消息格式轉換爲UTF8之前根據消息格式進行解析。這是因爲格式不僅僅是串在一起的一串字符。它們包括32位大端存儲和16位大端存儲。