私は、opensslを使ってCで小さなIRCボットを作成して、安全なソケットを開始します。最も美しく書かれたボットではありませんが、主にopenssl APIがどのように動作するかを見るだけです。現在、私は次のコードを持っています:BIO_do_connectの後にノンブロッキングBIOとハングアップ
#include <stdio.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
int main() {
SSL_load_error_strings();
ERR_load_BIO_strings();
OpenSSL_add_all_algorithms();
BIO *bio;
SSL_CTX * ctx = SSL_CTX_new(SSLv23_client_method());
SSL * ssl;
SSL_CTX_load_verify_locations(ctx, NULL, "/etc/ssl/certs/");
bio = BIO_new_ssl_connect(ctx);
BIO_get_ssl(bio, & ssl);
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
BIO_set_nbio(bio, 1);
BIO_set_conn_hostname(bio, "irc.freenode.net:6697");
BIO_do_connect(bio);
if(SSL_get_verify_result(ssl) != X509_V_OK) {
printf("error\n");
}
char irc1[] = "NICK bartender\r\n";
char irc2[] = "USER bartender * * :serve(&drinks);\r\n";
BIO_write(bio, irc1, strlen(irc1));
BIO_write(bio, irc2, strlen(irc2));
fd_set read_set;
int sock = BIO_get_fd(bio, NULL);
while(1) {
FD_ZERO(&read_set);
FD_SET(sock, &read_set);
struct timeval timeout = { 0, 0 };
select(sock+1, &read_set, NULL, NULL, &timeout);
if(FD_ISSET(sock, &read_set)) {
char buf[21];
size_t x = BIO_read(bio, buf, 20);
if(x == 0) {
continue;
} else if(x == -1){
int code = ERR_get_error();
if(code == 0) {
continue;
}
printf("(%d)%s\n", code, ERR_error_string(code, NULL));
} else {
buf[x] = '\0';
printf("%s", buf);
}
}
}
}
このコードをコンパイルして実行すると、何も表示されず、何も印刷されません。しかし、20行目(現在はソケットを非ブロックモードにしています)を削除しても正常に動作します。ソケットを非ブロッキングモードにすると、この動作が起こるのはなぜですか?ありがとう、素晴らしい一日を!
任意のソケットをJon-blockingモードにして、同じコードが動作し続けることを期待してください。より多くの作業が必要であり、SSLソケットのケースは非常に多いです。 OpenSSLのドキュメントを参照してください。広すぎます。 – EJP
私は「BIOオブジェクトを非ブロッキングモードにする」方法が広すぎます。それ以上のことが必要であると確信しています。そうでなければ、それは働くでしょう。何をする必要がありますか?私はすでにopensslのマニュアルページを読んで、googleと以前のSOの回答に相談しました。私は私がする必要がある何かを見つけることができません。 – DTSCode
もっと多くの帽子が必要ですが、* man select *とOpenSSLのドキュメントにはすべて記載されており、ここでは答えが広すぎます。 – EJP