Hier ist ein Beispiel eines HTTPS-Clients mit SSL unter Verwendung von libev.
Fügen Sie den folgenden Pfad oder Link zu xcode hinzu:
Header-Dateipfad | Pfad der Bibliotheksdatei | Abhängige Bibliotheken |
---|---|---|
usr/local/opt/openssl/include | /usr/local/opt/openssl/lib | libcrypto.a、libssl.a |
Ich blockiere die Verbindung. Wenn es kein Problem mit der Kommunikation gibt, wird das HTML der oberen Seite von Google auf der Konsole angezeigt.
Die Installation von libev finden Sie unter # 1.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string>
#include <ev.h>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#define SOCKET int
#define SD_BOTH SHUT_WR
#include <openssl/ssl.h>
#include <openssl/err.h>
#define READ_BUF_SIZE 4096
#define BUF_SIZE 4097
#define PORT 443
SSL *_ssl;
void close_socket(SOCKET socket, SSL_CTX *_ctx, SSL *_ssl){
// SSL/Beenden Sie die TLS-Verbindung.
SSL_shutdown(_ssl);
SSL_free(_ssl);
::shutdown(socket, SD_BOTH);
::close(socket);
SSL_CTX_free(_ctx);
ERR_free_strings();
}
int get_error(){
return errno;
}
//Vorbereitung auf SSL
SSL_CTX * ssl_setup(){
//Initialisierung der SSL-Bibliothek.
SSL_library_init();
//Vorbereiten der Fehlerbehebung.
SSL_load_error_strings();
//Globale Kontextinitialisierung.
const SSL_METHOD *meth = SSLv23_method();
return SSL_CTX_new(meth);
}
//TCP-Verbindung.
SOCKET tcp_connect(const char* host){
struct hostent *hp;
struct sockaddr_in addr;
SOCKET _socket;
if (!(hp = gethostbyname(host))){
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sin_addr = *(struct in_addr*)hp->h_addr_list[0];
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
if ((_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))<0){
return -1;
}
if (connect(_socket, (struct sockaddr *)&addr, sizeof(addr))<0){
return -1;
}
return _socket;
}
static void io_cb (EV_P_ ev_io *w, int revents)
{
char buf[BUF_SIZE] = { 0 };
char* p = buf;
int r = SSL_read(_ssl, p, READ_BUF_SIZE);
if(r > 0){
std::cout << p;
}
//Kommentieren Sie Folgendes aus, um mit einer Zeitüberschreitung zu beenden.
// I/Trennen Sie O von der Schleife.
//ev_io_stop (EV_A_ w);
//Unterbrechen Sie die Ereignisschleife.
//ev_unloop (EV_A_ EVUNLOOP_ALL);
}
static void timeout_cb (EV_P_ ev_timer *w, int revents)
{
std::cout << "timeout\n";
//Stoppen Sie den Timer.
ev_timer_stop (EV_A_ w);
//Unterbrechen Sie die Ereignisschleife.
ev_unloop (EV_A_ EVUNLOOP_ONE);
}
int main(int argc, const char * argv[])
{
std::string host = "www.google.co.jp";
SOCKET _socket = tcp_connect(host.c_str());
SSL_CTX *_ctx = ssl_setup();
//Erstellen Sie ein SSL-Sitzungsobjekt.
_ssl = SSL_new(_ctx);
//Mit Socket verknüpfen.
SSL_set_fd(_ssl, _socket);
//SSL-Verbindung.
int error = 0;
if (SSL_connect(_ssl) <= 0){
error = get_error();
::shutdown(_socket, SD_BOTH);
close_socket(_socket, _ctx, _ssl);
return 0;
}
//Auf nicht blockierend einstellen.
int flag = fcntl(_socket, F_GETFL, 0);
fcntl(_socket, F_SETFL, flag | O_NONBLOCK);
//Erstellen Sie eine Ereignisschleife.
struct ev_loop *loop = ev_loop_new (0);
// I/O Objekt beobachten.
ev_io io_watcher;
// I/Für O Objekte beobachten
//Verknüpfen Sie Rückrufe mit FDs mit Ereignistypen.
ev_io_init (&io_watcher, io_cb, _socket, EV_READ);
// I/Verknüpfen Sie eine Ereignisschleife mit einem O-Überwachungsobjekt.
ev_io_start (loop, &io_watcher);
//Erstellen Sie ein Timer-Objekt.
ev_timer timeout_watcher;
//Verknüpfen Sie einen Rückruf mit einem Zeitgeberobjekt und geben Sie eine Zeitüberschreitung an.
ev_timer_init (&timeout_watcher, timeout_cb, 20, 0.);
//Verknüpfen Sie eine Ereignisschleife mit einem Timer-Objekt.
ev_timer_start (loop, &timeout_watcher);
std::string str = "GET / HTTP/1.1\r\nHost: " + host;
str = str + "\r\n\r\n";
int w = SSL_write(_ssl, str.c_str(), static_cast<int>(str.length()));
std::cout << "write count" << w << "\n";
//Schleifenstart.
ev_loop (loop, 0);
//Wenn Sie nicht blockieren möchten.
//ev_loop (loop, EVLOOP_NONBLOCK);
std::cout << "end\n";
//Verwerfen Sie die erstellte Ereignisschleife
ev_loop_destroy(loop);
close_socket(_socket, _ctx, _ssl);
return 0;
}
Kompilieren Sie mit gcc
gcc -o test test.cpp -lev -I/usr/local/Cellar/libev/4.15/include/ -L/usr/local/Cellar/libev/4.15/lib/ -L/usr/local/opt/openssl/lib -I/usr/local/opt/openssl/include -lcrypto -lssl -lstdc++
Recommended Posts