[英]select() always returns 1; TCP connected socket troubles in c++
[英]OpenSSL socket: Select always returns 0
我制作了一個帶有阻塞套接字的小型套接字回顯服務器(請參見下面的代碼),但是即使有一條要讀取的消息,select語句也始終返回0。 其他一切正常。 如果通過簡單地將1 selectResult
來替換select語句,則服務器可以工作。
服務器在VM的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;
}
我認為您打算在剛剛接受的client
套接字上進行選擇,而不是在接受連接的_serverSocket
上進行選擇。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.