Voici un exemple de client HTTPS avec SSL utilisant libev.
Ajoutez le chemin ou le lien suivant vers xcode:
Chemin du fichier d'en-tête | Chemin du fichier de bibliothèque | Bibliothèques dépendantes |
---|---|---|
usr/local/opt/openssl/include | /usr/local/opt/openssl/lib | libcrypto.a、libssl.a |
Je bloque la connexion. S'il n'y a pas de problème de communication, le html de la première page de google sera affiché sur la console.
Veuillez consulter # 1 pour l'installation de libev.
#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/Arrêtez la connexion TLS.
SSL_shutdown(_ssl);
SSL_free(_ssl);
::shutdown(socket, SD_BOTH);
::close(socket);
SSL_CTX_free(_ctx);
ERR_free_strings();
}
int get_error(){
return errno;
}
//Préparer SSL
SSL_CTX * ssl_setup(){
//Initialisation de la bibliothèque SSL.
SSL_library_init();
//Préparation à la chaîne de l'erreur.
SSL_load_error_strings();
//Initialisation du contexte global.
const SSL_METHOD *meth = SSLv23_method();
return SSL_CTX_new(meth);
}
//Connexion TCP.
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;
}
//Commentez ce qui suit pour terminer avec un délai d'attente.
// I/Dissocier O de la boucle.
//ev_io_stop (EV_A_ w);
//Briser la boucle des événements.
//ev_unloop (EV_A_ EVUNLOOP_ALL);
}
static void timeout_cb (EV_P_ ev_timer *w, int revents)
{
std::cout << "timeout\n";
//Arrêtez le chronomètre.
ev_timer_stop (EV_A_ w);
//Briser la boucle des événements.
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();
//Créer un objet de session SSL.
_ssl = SSL_new(_ctx);
//Associer avec socket.
SSL_set_fd(_ssl, _socket);
//Connexion SSL.
int error = 0;
if (SSL_connect(_ssl) <= 0){
error = get_error();
::shutdown(_socket, SD_BOTH);
close_socket(_socket, _ctx, _ssl);
return 0;
}
//Défini sur non bloquant.
int flag = fcntl(_socket, F_GETFL, 0);
fcntl(_socket, F_SETFL, flag | O_NONBLOCK);
//Créer une boucle d'événements.
struct ev_loop *loop = ev_loop_new (0);
// I/Ô objet de montre.
ev_io io_watcher;
// I/Pour les objets O watch
//Associer des rappels aux FD avec des types d'événements.
ev_io_init (&io_watcher, io_cb, _socket, EV_READ);
// I/Associer une boucle d'événement à un objet O watch.
ev_io_start (loop, &io_watcher);
//Créer un objet minuterie.
ev_timer timeout_watcher;
//Associer un rappel à un objet timer et spécifier un timeout.
ev_timer_init (&timeout_watcher, timeout_cb, 20, 0.);
//Associer une boucle d'événements à un objet timer.
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";
//Début de boucle.
ev_loop (loop, 0);
//Si vous ne voulez pas bloquer.
//ev_loop (loop, EVLOOP_NONBLOCK);
std::cout << "end\n";
//Supprimer la boucle d'événements créée
ev_loop_destroy(loop);
close_socket(_socket, _ctx, _ssl);
return 0;
}
Compiler avec 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