2015-05-27 2 views
0

Я сделал небольшой эхо-сервер сокета с блокирующим сокетом (см. Код ниже), но оператор select всегда возвращает 0, даже когда есть сообщение для чтения. Все остальное работает. Если вы замените оператор select простым присваиванием 1 selectResult, сервер работает.OpenSSL-сокет: всегда всегда возвращается 0

Сервер работает на Ubuntu на виртуальной машине, а клиент находится на хост-системе (Windows 7 professional). Моя IDE для сервера Eclipse 3.8 и использует OpenSSL 1.0.1j.

Для того, чтобы этот код работал, вам необходимо включить в него корневой каталог OpenSSL, добавить его путь к библиотеке и ссылку на ssl, crypto и dl (в указанном порядке). Также вам нужен сертификат и закрытый ключ.

Заранее благодарен!

#include <openssl/ssl.h> 
#include <openssl/err.h> 
#include <sys/socket.h> 
#include <unistd.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <iostream> 

using namespace std; 
#define MAX_BUFFER 1024 

int main() 
{ 
    // Initializing... 
    SSL_CTX*_ctx = NULL; 
    SSL* _ssl = NULL; 
    fd_set _fdSet; 
    int _serverSocket = 0; 
    int _port = 9090; 
    timeval t; 
    const char* certPath = "/home/alex/Certificate/cacert.pem"; 
    const char* pKeyPath = "/home/alex/Certificate/privkey.pem"; 

    // Init OpenSSL 
    SSL_library_init(); 
    SSL_load_error_strings(); 
    OpenSSL_add_all_algorithms(); 
    _ctx = SSL_CTX_new(TLSv1_1_server_method()); 
    if (_ctx == NULL) 
    { 
     ERR_print_errors_fp(stderr); 
     abort(); 
    } 

    // Set certificate and private key. 
    if (SSL_CTX_use_certificate_file(_ctx, certPath, SSL_FILETYPE_PEM) <= 0) 
    { 
     ERR_print_errors_fp(stderr); 
     abort(); 
    } 
    if (SSL_CTX_use_PrivateKey_file(_ctx, pKeyPath, SSL_FILETYPE_PEM) <= 0) 
    { 
     ERR_print_errors_fp(stderr); 
     abort(); 
    } 
    if (!SSL_CTX_check_private_key(_ctx)) 
    { 
     fprintf(stderr, "Private key does not match the public certificate\n"); 
     abort(); 
    } 

    // Initialize server socket: 
    // 1. set address 
    struct sockaddr_in addr; 
    int optval = 1; 
    bzero(&addr, sizeof(addr)); 
    addr.sin_family = AF_INET; 
    addr.sin_port = htons(_port); 
    addr.sin_addr.s_addr = INADDR_ANY; 

    // 2. init socket, set socket options, bind it to address 
    _serverSocket = socket(PF_INET, SOCK_STREAM, 0); 
    setsockopt(_serverSocket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); 
    if (bind(_serverSocket, (struct sockaddr*) &addr, sizeof(addr)) != 0) 
    { 
     perror("can't bind port"); 
     abort(); 
    } 
    // 3. Prepare the socket to accept connections 
    if (listen(_serverSocket, 1) != 0) 
    { 
     perror("Can't configure listening port"); 
     abort(); 
    } 
    cout << "Server finished initializing." << endl; 

    bool bServerStayAlive = true; 
    while (bServerStayAlive) 
    { 
     cout << "Waiting for connection..." << endl; 
     struct sockaddr_in addr; 
     unsigned int len = sizeof(addr); 
     int client = accept(_serverSocket, (struct sockaddr*) &addr, &len); 

     printf("Connection: %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); 
     _ssl = SSL_new(_ctx); 
     SSL_set_fd(_ssl, client); 
     if (SSL_accept(_ssl) == -1) /* do SSL-protocol accept */ 
      ERR_print_errors_fp(stderr); 
     else 
     { 
      while (bServerStayAlive) 
      { 
       FD_ZERO(&_fdSet); 
       FD_SET(_serverSocket, &_fdSet); 
       t.tv_sec = 1; 
       t.tv_usec = 0; 
       int selectResult = select(_serverSocket + 1, &_fdSet, NULL, NULL, &t); 
       if (selectResult == 0) 
       { 
        cout << "timeout" << endl; 
        continue; 
       } 
       if (selectResult < 0) 
       { 
        cout << "Select error: " << selectResult << endl; 
        bServerStayAlive = false; 
        break; 
       } 

       cout << "Going to read something\n"; 
       unsigned char buffer[MAX_BUFFER]; 
       memset(buffer, 0, MAX_BUFFER); 
       int bytes = SSL_read(_ssl, buffer, MAX_BUFFER); /* get request */ 
       if (bytes > 0) 
       { 
        cout << "Received message: " << endl; 
        for (int i = 0; i < bytes; i++) 
         cout << buffer[i]; 
        cout << endl; 
        SSL_write(_ssl, buffer, bytes); 
       } 
       else 
       { 
        ERR_print_errors_fp(stderr); 
        break; 
       } 
      } 
     } 
     int sd = SSL_get_fd(_ssl); /* get socket connection */ 
     SSL_free(_ssl); /* release SSL state */ 
     close(sd); /* close connection */ 
     cout << "Connection was closed.\n"; 
    } 
    // Uninitializing 
    close(_serverSocket); 
    SSL_CTX_free(_ctx); 
    return 0; 
} 

ответ

2

Я думаю, что вы имели в виду, чтобы выбрать на client сокет, который вы только что приняли, а не _serverSocket, что вы принимающему соединения на.

+0

Да, это все! Спасибо огромное! – Alex

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