2016-12-09 7 views
0

Я читал протокол Postgresql провода и возникают проблемы реализации раздел, связанный с простыми запросами, где spec говорит:Проблема понимания определение протокола

Query (F) 
    Byte1('Q') 
    Identifies the message as a simple query. 

    Int32 
    Length of message contents in bytes, including self. 

    String 
    The query string itself. 

я придумал следующее C++:

(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >) $0 = size=31 { 
    [0] = 'Q' 
    [1] = '\0' 
    [2] = '\0' 
    [3] = '\0' 
    [4] = '\x1f' 
    [5] = 's' 
    [6] = 'e' 
    [7] = 'l' 
    [8] = 'e' 
    [9] = 'c' 
    [10] = 't' 
    [11] = ' ' 
    [12] = '*' 
    [13] = ' ' 
    [14] = 'f' 
    [15] = 'r' 
    [16] = 'o' 
    [17] = 'm' 
    [18] = ' ' 
    [19] = 'd' 
    [20] = 'e' 
    [21] = 'p' 
    [22] = 'a' 
    [23] = 'r' 
    [24] = 't' 
    [25] = 'm' 
    [26] = 'e' 
    [27] = 'n' 
    [28] = 't' 
    [29] = 's' 
    [30] = '\0' 
} 

Но я всегда получаю сообщение об ошибке с сервера:

EJSERRORC08P01Minvalid message formatFpqformat.cL652Rpq_getmsgendETSFATALC08P01Minvalid frontend message type 0Fpostgres.cL484RSocketBackend 

На этом этапе я устал бросать разные версии этого вектора на сервер, чтобы всегда получать одинаковый результат, поэтому я предполагаю, что моя интерпретация спецификации неверна. Можете ли вы показать мне код, как это будет сделано? Не алго генерировать сообщение, просто действительное сообщение.

+0

Я ничего о протоколе PostGreSQL провода не знаю, но: 1) вы установите длину 27, даже если все сообщение имеет длину 28 байт; 2) возможно, он должен что-то сделать с байтом порядка Int32? – gudok

+0

@ gudok Скопированный неправильный вектор. – ruipacheco

+0

@gudok - клиент и сервер находятся на одной машине, поэтому это не должно быть проблемой, нет? – ruipacheco

ответ

2

Поскольку вы не делитесь своим кодом, я не могу сказать, где вы поступили не так.

Ваше сообщение нормально, за исключением того, что длина должна быть 30 ('\x1e') вместо 31 ('\x1f') – согласно the documentation, то “ типа сообщения байт ” не должен учитываться.

Я попробовал это с помощью C на Linux, и это сработало для меня.

Я отправил сообщение с send() над гнездом меня с PQsocket(), и я получил ответ, который состоял из:

  1. Один RowDescription сообщения (типа 'T'), описывающий столбцы.

  2. данныеRow сообщение (тип 'D') за возвращенный столбец.

  3. Закрыть Сообщение (тип 'C'), закрывающее заявление.

  4. ReadyForQuery (тип 'Z') сообщение.

Для записи, вот код C я использовал:

#include <libpq-fe.h> 
#include <stdio.h> 
#include <string.h> 
#include <errno.h> 
#include <sys/types.h> 
#include <sys/socket.h> 

#define BUFSIZE 1000 

int main(int argc, char **argv) { 
    /* PostgreSQL database connection */ 
    PGconn *conn; 
    /* socket for the database connection */ 
    int s; 
    /* simple select statement to send over the socket */ 
    unsigned char stmt[] = "Q\0\0\0\030select * from amaaa"; 
    /* buffer for the server response */ 
    unsigned char buf[BUFSIZE]; 
    ssize_t len, i; 

    /* connect to the database */ 
    conn = PQconnectdb(""); 
    if (conn == NULL) 
    { 
     fprintf(stderr, "Out of memory connecting to PostgreSQL.\n"); 
     return 1; 
    } 
    if (PQstatus(conn) != CONNECTION_OK) 
    { 
     fprintf(stderr, "%s\n", PQerrorMessage(conn)); 
     PQfinish(conn); 
     return 1; 
    } 

    /* get the TCP socket that corresponds to the connection */ 
    if ((s = PQsocket(conn)) <= 0) 
    { 
     fprintf(stderr, "Connection is not open.\n"); 
     PQfinish(conn); 
     return 1; 
    } 

    /* send the simple select statement */ 
    if (-1 == send(s, stmt, sizeof(stmt), 0)) 
    { 
     perror("Error in send(2)"); 
     PQfinish(conn); 
     return 1; 
    } 

    /* 
    * The following is oversimplified. 
    * In reality, you'd have to call recv(2) until you have 
    * the complete response. 
    * But I don't want to bother with analyzing the response 
    * and hope that it comes in a single packet. 
    */ 

    /* receive the response */ 
    if (-1 == (len = recv(s, buf, BUFSIZE, MSG_WAITALL))) 
    { 
     perror("Error in recv(2)"); 
     PQfinish(conn); 
     return 1; 
    } 

    /* print the server response */ 
    for (i=0; i<len; ++i) { 
     if (buf[i] >= ' ' && buf[i] <= 'z') 
      printf("%02X(%c) ", buf[i], buf[i]); 
     else 
      printf("%02X ", buf[i]); 
    } 
    printf("\n"); 

    /* close the database connection */ 
    PQfinish(conn); 

    return 0; 
} 
+0

Я собираюсь принять это, поскольку он дал мне хорошее представление о том, что делать дальше. – ruipacheco

+0

Я также получаю сокет, но получаю ту же ошибку. Можете ли вы вставить код, который вы написали в качестве руководства? – ruipacheco

+0

Правильно, ваш код не будет работать. Даже создал таблицу под названием amaaa. Я по-прежнему получаю ту же ошибку, что и мой первоначальный ответ. Странно то, что все аутентификационное рукопожатие отлично работает. – ruipacheco

 Смежные вопросы

  • Нет связанных вопросов^_^