OpenSSL之ssl库_ssl_read_ex-程序员宅基地

技术标签: openssl  

ssl

OpenSSL的SSL/TLS库,实现了SSL(Secur)/TLS(Transport Layer Security)/DTLS(Datagram Transport Layer Security)协议的多个版本。

SSL_CTX对象包含证书、算法等信息,用于建立TLS/SSL连接。

网络连接建立后可以赋值给SSL对象,然后可以使用SSL对象完成握手操作(SSL_accept或SSL_connect或SSL_do_handshake),握手完成后就可以读写了。关闭网络连接前先调用SSL_shutdown关闭TLS/SSL连接。

  • SSL_METHOD 特定协议的操作函数,创建SSL_CTX时需要
  • SSL_CIPHER 加密算法信息,可以在SSL_CTX中指定可用的算法集合,SSL_SESSION中会记录实际使用的算法。
  • SSL_CTX 全局配置,包含SSL配置的默认值。
  • SSL_SESSION 包含当前session信息的结构,包括:加密算法、证书、密钥等
  • SSL SSL连接,

使用证书和密钥

        #include <openssl/ssl.h>

        /* CA 设置 */
        int SSL_CTX_load_verify_dir(SSL_CTX *ctx, const char *CApath);
        int SSL_CTX_load_verify_file(SSL_CTX *ctx, const char *CAfile);
        int SSL_CTX_load_verify_store(SSL_CTX *ctx, const char *CAstore);

        int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx);

        int SSL_CTX_set_default_verify_dir(SSL_CTX *ctx);
        int SSL_CTX_set_default_verify_file(SSL_CTX *ctx);
        int SSL_CTX_set_default_verify_store(SSL_CTX *ctx);

        int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
                                          const char *CApath);

        /* CA证书相关操作 */
        void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *list);
        void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *list);
        STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s);
        STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx);
        int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *cacert);
        int SSL_add_client_CA(SSL *ssl, X509 *cacert);

        void SSL_CTX_set0_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list);
        void SSL_set0_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list);
        const STACK_OF(X509_NAME) *SSL_CTX_get0_CA_list(const SSL_CTX *ctx);
        const STACK_OF(X509_NAME) *SSL_get0_CA_list(const SSL *s);
        int SSL_CTX_add1_to_CA_list(SSL_CTX *ctx, const X509 *x);
        int SSL_add1_to_CA_list(SSL *ssl, const X509 *x);

        const STACK_OF(X509_NAME) *SSL_get0_peer_CA_list(const SSL *s);

        /* 证书链设置 */
        int SSL_CTX_set0_chain(SSL_CTX *ctx, STACK_OF(X509) *sk);
        int SSL_CTX_set1_chain(SSL_CTX *ctx, STACK_OF(X509) *sk);
        int SSL_CTX_add0_chain_cert(SSL_CTX *ctx, X509 *x509);
        int SSL_CTX_add1_chain_cert(SSL_CTX *ctx, X509 *x509);
        int SSL_CTX_get0_chain_certs(SSL_CTX *ctx, STACK_OF(X509) **sk);
        int SSL_CTX_clear_chain_certs(SSL_CTX *ctx);

        int SSL_set0_chain(SSL *ssl, STACK_OF(X509) *sk);
        int SSL_set1_chain(SSL *ssl, STACK_OF(X509) *sk);
        int SSL_add0_chain_cert(SSL *ssl, X509 *x509);
        int SSL_add1_chain_cert(SSL *ssl, X509 *x509);
        int SSL_get0_chain_certs(SSL *ssl, STACK_OF(X509) **sk);
        int SSL_clear_chain_certs(SSL *ssl);

        int SSL_CTX_build_cert_chain(SSL_CTX *ctx, flags);
        int SSL_build_cert_chain(SSL *ssl, flags);

        /* 证书和密钥设置 */
        int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);
        int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d);
        int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type);
        int SSL_use_certificate(SSL *ssl, X509 *x);
        int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len);
        int SSL_use_certificate_file(SSL *ssl, const char *file, int type);

        int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file);
        int SSL_use_certificate_chain_file(SSL *ssl, const char *file);

        int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);
        int SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx, const unsigned char *d,
                                        long len);
        int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type);
        int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa);
        int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len);
        int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type);
        int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey);
        int SSL_use_PrivateKey_ASN1(int pk, SSL *ssl, const unsigned char *d, long len);
        int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type);
        int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa);
        int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const unsigned char *d, long len);
        int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type);

        int SSL_CTX_check_private_key(const SSL_CTX *ctx);
        int SSL_check_private_key(const SSL *ssl);

        int SSL_CTX_use_cert_and_key(SSL_CTX *ctx, X509 *x, EVP_PKEY *pkey, STACK_OF(X509) *chain, int override);
        int SSL_use_cert_and_key(SSL *ssl, X509 *x, EVP_PKEY *pkey, STACK_OF(X509) *chain, int override);

        /* 证书选择 */
        int SSL_CTX_select_current_cert(SSL_CTX *ctx, X509 *x509);
        int SSL_select_current_cert(SSL *ssl, X509 *x509);
        int SSL_CTX_set_current_cert(SSL_CTX *ctx, long op);
        int SSL_set_current_cert(SSL *ssl, long op);

SSL_CTX操作

        #include <openssl/ssl.h>

        SSL_CTX *SSL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq,
                                const SSL_METHOD *method);
        SSL_CTX *SSL_CTX_new(const SSL_METHOD *method);
        int SSL_CTX_up_ref(SSL_CTX *ctx);

        const SSL_METHOD *TLS_method(void);
        const SSL_METHOD *TLS_server_method(void);
        const SSL_METHOD *TLS_client_method(void);

        const SSL_METHOD *SSLv23_method(void);
        const SSL_METHOD *SSLv23_server_method(void);
        const SSL_METHOD *SSLv23_client_method(void);

        #ifndef OPENSSL_NO_SSL3_METHOD
        const SSL_METHOD *SSLv3_method(void);
        const SSL_METHOD *SSLv3_server_method(void);
        const SSL_METHOD *SSLv3_client_method(void);
        #endif

        #ifndef OPENSSL_NO_TLS1_METHOD
        const SSL_METHOD *TLSv1_method(void);
        const SSL_METHOD *TLSv1_server_method(void);
        const SSL_METHOD *TLSv1_client_method(void);
        #endif

        #ifndef OPENSSL_NO_TLS1_1_METHOD
        const SSL_METHOD *TLSv1_1_method(void);
        const SSL_METHOD *TLSv1_1_server_method(void);
        const SSL_METHOD *TLSv1_1_client_method(void);
        #endif

        #ifndef OPENSSL_NO_TLS1_2_METHOD
        const SSL_METHOD *TLSv1_2_method(void);
        const SSL_METHOD *TLSv1_2_server_method(void);
        const SSL_METHOD *TLSv1_2_client_method(void);
        #endif

        const SSL_METHOD *DTLS_method(void);
        const SSL_METHOD *DTLS_server_method(void);
        const SSL_METHOD *DTLS_client_method(void);

        #ifndef OPENSSL_NO_DTLS1_METHOD
        const SSL_METHOD *DTLSv1_method(void);
        const SSL_METHOD *DTLSv1_server_method(void);
        const SSL_METHOD *DTLSv1_client_method(void);
        #endif

        #ifndef OPENSSL_NO_DTLS1_2_METHOD
        const SSL_METHOD *DTLSv1_2_method(void);
        const SSL_METHOD *DTLSv1_2_server_method(void);
        const SSL_METHOD *DTLSv1_2_client_method(void);
        #endif

        void SSL_CTX_free(SSL_CTX *ctx);

        uint64_t SSL_CTX_set_options(SSL_CTX *ctx, uint64_t options);
        uint64_t SSL_set_options(SSL *ssl, uint64_t options);

        uint64_t SSL_CTX_clear_options(SSL_CTX *ctx, uint64_t options);
        uint64_t SSL_clear_options(SSL *ssl, uint64_t options);

        uint64_t SSL_CTX_get_options(const SSL_CTX *ctx);
        uint64_t SSL_get_options(const SSL *ssl);

        long SSL_get_secure_renegotiation_support(SSL *ssl);


        typedef int (*SSL_verify_cb)(int preverify_ok, X509_STORE_CTX *x509_ctx);

        void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, SSL_verify_cb verify_callback);
        void SSL_set_verify(SSL *ssl, int mode, SSL_verify_cb verify_callback);
        SSL_get_ex_data_X509_STORE_CTX_idx(void);

        void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth);
        void SSL_set_verify_depth(SSL *ssl, int depth);

        int SSL_verify_client_post_handshake(SSL *ssl);
        void SSL_CTX_set_post_handshake_auth(SSL_CTX *ctx, int val);
        void SSL_set_post_handshake_auth(SSL *ssl, int val);


        int SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version);
        int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version);
        int SSL_CTX_get_min_proto_version(SSL_CTX *ctx);
        int SSL_CTX_get_max_proto_version(SSL_CTX *ctx);

        int SSL_set_min_proto_version(SSL *ssl, int version);
        int SSL_set_max_proto_version(SSL *ssl, int version);
        int SSL_get_min_proto_version(SSL *ssl);
        int SSL_get_max_proto_version(SSL *ssl);


        X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx);
        X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl);
        int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm);
        int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm);
        

一些SSL_CTX中的设置也可以在SSL中单独设置或修改,接口也一并在此列出。

SSL_CONF_CTX操作

        #include <openssl/ssl.h>

        SSL_CONF_CTX *SSL_CONF_CTX_new(void);
        void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx);

        unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags);
        unsigned int SSL_CONF_CTX_clear_flags(SSL_CONF_CTX *cctx, unsigned int flags);

        unsigned int SSL_CONF_CTX_set1_prefix(SSL_CONF_CTX *cctx, const char *prefix);

        int SSL_CONF_cmd(SSL_CONF_CTX *ctx, const char *option, const char *value);
        int SSL_CONF_cmd_value_type(SSL_CONF_CTX *ctx, const char *option);

        int SSL_CONF_cmd_argv(SSL_CONF_CTX *cctx, int *pargc, char ***pargv);

        void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx);
        void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl);

SSL基本操作

        #include <openssl/ssl.h>

        SSL *SSL_new(SSL_CTX *ctx);
        SSL *SSL_dup(SSL *s);
        int SSL_up_ref(SSL *s);
        void SSL_free(SSL *ssl);

        int SSL_set_fd(SSL *ssl, int fd);
        int SSL_set_rfd(SSL *ssl, int fd);
        int SSL_set_wfd(SSL *ssl, int fd);
        
        int SSL_get_fd(const SSL *ssl);
        int SSL_get_rfd(const SSL *ssl);
        int SSL_get_wfd(const SSL *ssl);
        
        void SSL_set_bio(SSL *ssl, BIO *rbio, BIO *wbio);
        void SSL_set0_rbio(SSL *s, BIO *rbio);
        void SSL_set0_wbio(SSL *s, BIO *wbio);

        BIO *SSL_get_rbio(SSL *ssl);
        BIO *SSL_get_wbio(SSL *ssl);
                
        int SSL_accept(SSL *ssl);
        int SSL_connect(SSL *ssl);

        void SSL_set_connect_state(SSL *ssl);
        void SSL_set_accept_state(SSL *ssl);
        int SSL_is_server(const SSL *ssl);
        int SSL_do_handshake(SSL *ssl);
        
        int SSL_shutdown(SSL *ssl);
        int SSL_get_shutdown(const SSL *ssl);
        int SSL_clear(SSL *ssl);

        ossl_ssize_t SSL_sendfile(SSL *s, int fd, off_t offset, size_t size, int flags);
        int SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *written);
        int SSL_write(SSL *ssl, const void *buf, int num);

        int SSL_pending(const SSL *ssl);
        int SSL_has_pending(const SSL *s);
        
        int SSL_read_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes);
        int SSL_read(SSL *ssl, void *buf, int num);

        int SSL_peek_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes);
        int SSL_peek(SSL *ssl, void *buf, int num);

        int SSL_get_error(const SSL *ssl, int ret);

这些SSL函数不包含socket的基础操作,必须跟系统的socket或BIO结合使用。

   The behaviour of SSL_accept() depends on the underlying BIO.

   If the underlying BIO is blocking, SSL_accept() will only return once the handshake has been finished or an error occurred.

   If the underlying BIO is nonblocking, SSL_accept() will also return when the underlying BIO could not satisfy the needs of
   SSL_accept() to continue the handshake, indicating the problem by the return value -1.  In this case a call to SSL_get_error() with
   the return value of SSL_accept() will yield SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE. The calling process then must repeat the
   call after taking appropriate action to satisfy the needs of SSL_accept().  The action depends on the underlying BIO. When using a
   nonblocking socket, nothing is to be done, but select() can be used to check for the required condition. When using a buffering BIO,
   like a BIO pair, data must be written into or retrieved out of the BIO before being able to continue.

基于BIO的SSL操作

BIO socket 操作

#include <openssl/bio.h>

const BIO_METHOD *BIO_s_accept(void);

long BIO_set_accept_name(BIO *b, char *name);
char *BIO_get_accept_name(BIO *b);

long BIO_set_accept_port(BIO *b, char *port);
char *BIO_get_accept_port(BIO *b);

BIO *BIO_new_accept(char *host_port);

long BIO_set_nbio_accept(BIO *b, int n);
long BIO_set_accept_bios(BIO *b, char *bio);

char *BIO_get_peer_name(BIO *b);
char *BIO_get_peer_port(BIO *b);
long BIO_get_accept_ip_family(BIO *b);
long BIO_set_accept_ip_family(BIO *b, long family);

long BIO_set_bind_mode(BIO *b, long mode);
long BIO_get_bind_mode(BIO *b);

int BIO_do_accept(BIO *b);

注意:上述操作仅是socket操作,没有涉及SSL相关内容,要实现SSL通信,还需要结合以下SSL操作

SSL BIO操作

#include <openssl/bio.h>
#include <openssl/ssl.h>

const BIO_METHOD *BIO_f_ssl(void);

long BIO_set_ssl(BIO *b, SSL *ssl, long c);
long BIO_get_ssl(BIO *b, SSL **sslp);
long BIO_set_ssl_mode(BIO *b, long client);
long BIO_set_ssl_renegotiate_bytes(BIO *b, long num);
long BIO_set_ssl_renegotiate_timeout(BIO *b, long seconds);
long BIO_get_num_renegotiates(BIO *b);

BIO *BIO_new_ssl(SSL_CTX *ctx, int client);
BIO *BIO_new_ssl_connect(SSL_CTX *ctx);
BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx);
int BIO_ssl_copy_session_id(BIO *to, BIO *from);
void BIO_ssl_shutdown(BIO *bio);

long BIO_do_handshake(BIO *b);

操作是否需要重试

在非阻塞模式下,操作无法立即完成时会返回错误,应用需要判断是需要重试还是真的有错误,判断是否需要重试、重试的原因和重试的操作:

int BIO_should_read(BIO *b);
int BIO_should_write(BIO *b);
int BIO_should_io_special(iBIO *b);
int BIO_retry_type(BIO *b);
int BIO_should_retry(BIO *b);

BIO *BIO_get_retry_BIO(BIO *bio, int *reason);
int BIO_get_retry_reason(BIO *bio);
void BIO_set_retry_reason(BIO *bio, int reason);

关于accept socket的非阻塞模块

设置非阻塞模式:long BIO_set_nbio_accept(BIO *b, int n);

   If the underlying accept socket is nonblocking and BIO_do_accept() is called to await an incoming connection it is possible for
   BIO_should_io_special() with the reason BIO_RR_ACCEPT. If this happens then it is an indication that an accept attempt would block:
   the application should take appropriate action to wait until the underlying socket has accepted a connection and retry the call.

如果accept socket是非阻塞模式,调用BIO_do_accept来等待连接,当前没有连接时会返回错误,BIO_should_retry会返回true,说明操作需要重试,BIO_should_io_special会返回true并且BIO_get_retry_reason会返回 BIO_RR_ACCEPT,这种情况说明accept操作需要阻塞等待,应用程序应该等待直到底层socket接受一个连接后再重试BIO_do_accept。等待可用使用select/poll/epoll来实现。

demo解读

server-arg

  • 首先需要构建一个用于server端的SSL_CTX对象ctx:ctx = SSL_CTX_new(TLS_server_method());
  • 再构建一个SSL_CONF_CTX对象cctx对ctx进行配置:cctx = SSL_CONF_CTX_new(); SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
  • 构建server socket BIO: in = BIO_new_accept(port) 等价于:
    BIO * in = BIO_new(BIO_s_accept());
    BIO_set_accept_name(in, port)
    
  • 构建一个用于server端连接的BIO:ssl_bio = BIO_new_ssl(ctx, 0);
    将ssl_bio指定用于server socket传入连接BIO的处理,每个传入连接会复制ssl_bio对象(链),使用ssl_bio一致的方式处理传入连接,即相当于:
    int fd = accept();
    BIO* conn_io = BIO_new_fd(fd, 1);
    ssl_io = BIO_dup_chain(ssl_bio);
    BIO_push(ssl_io, conn_io);
    
  • 接受连接:BIO_do_accept(in)
  • 接受连接后,进行读写操作BIO_read(in, buf, 512);
    新建连接对应的BIO对象被串到accept BIO之后,即accept->socket,此时读写accept BIO对象,相当于读写socket BIO,而没有接受连接之前读写accept BIO,accept BIO在BIO链的末端,会先等待连接,再在socket BIO上执行读写操作。而之前还调用了BIO_set_accept_bios(),BIO链应该是accept->otherbios->socket。
  • 连接用完之后要关闭它,先将它从BIO链中移除:tmp = BIO_pop(in);
    这里返回的tmp实际是BIO链otherbios->socket,可以关闭它,也可以做其他IO操作,需要并发处理多个连接时,通常在BIO_do_accept之后,执行BIO_pop得到对应连接的BIO,进行后续处理,而accept BIO就可以再次执行BIO_do_accept
  • 关闭socket BIO:BIO_free_all(tmp);
    注意这里是一个BIO链,所以用BIO_free_all全部关闭。
  • 最后关闭accept BIO:IO_free(in);
    关闭accept BIO的同时会自动关闭之前设置的ssl_bio。

client-arg

  • 构建一个用于client端的SSL_CTX对象ctx:ctx = SSL_CTX_new(TLS_client_method());
  • 再构建一个SSL_CONF_CTX对象cctx对ctx进行配置:cctx = SSL_CONF_CTX_new(); SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
  • 创建用于客户端连接的BIO对象:sbio = BIO_new_ssl_connect(ctx);
  • 指定服务端地址端口:BIO_set_conn_hostname(sbio, connect_str);
  • 连接到服务器:BIO_do_connect(sbio)
  • 发送请求:BIO_puts(sbio, “GET / HTTP/1.0\n\n”);
  • 读应答:BIO_read(sbio, tmpbuf, 1024);
  • 关闭连接:BIO_free_all(sbio);
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/doushi/article/details/122796627

智能推荐

STM32 精确控制PWM脉冲个数_stm32控制pwm脉冲数量-程序员宅基地

文章浏览阅读2.1w次,点赞29次,收藏252次。一般情况下我们在控制指定书目PWM输出的时候,都是采用在对每一次的脉冲中断进行,虽然也能产生对硬件的PWM脉冲数目精确控制,但却是通过对每一次的脉冲都进行计数实现的,然而有的情况下我们用到PWM脉冲周期可能会达到us级甚至更低,这样的情况下,对于中断频繁计数脉冲这种状况,会非常的占用MCU的资源,甚至严重的情况下 可能会影响到程序的运行。下面介绍一种,无需对脉冲个数每个都进行计数而是产生指定脉冲个..._stm32控制pwm脉冲数量

在DirectX 8 中进行2D渲染_d3d8绘制一张图片-程序员宅基地

文章浏览阅读508次。Background背景I have been reading alot of questions lately related to DirectX 8 and the exclusion of DirectDraw from the new API. Many people have fallen back to DX7. I can understand people using_d3d8绘制一张图片

2024程序员IDEA插件推荐!!!_2024 idea插件推荐-程序员宅基地

文章浏览阅读1k次。2024年程序员IDEA插件推荐!!!为了能更好的写出代码(BUG),为了装杯,一起装起来吧。_2024 idea插件推荐

工作资料(kernel)-----unbalanced enable irq 问题的解决 以及共享的gpio中断引起的问题_如何避免unbalanced enable for irq-程序员宅基地

文章浏览阅读494次。最近在工作中使用irq时遇到如下问题,根据log显示应该是什么所谓的不平横问题,先前也没有仔细研究这个问题,只是定位到是enable_irq函数调用所致。因为在项目中使用的中断是gpio中断,该中断在项目中的实现方式为多个gpio中断共享一个真实的物理中断,因此当这个真实的物理中断发生后由系统(就是另一个哥们写的irq驱动)查询到底是连接到这个物理中断上的哪一个具体的gpio产生的了中断(通过_如何避免unbalanced enable for irq

解决CSerialPort串口通讯类单字符接收的问题⑤_cserialport接收字符-程序员宅基地

文章浏览阅读1.3k次。http://chaochaoblog.com/archives/3500在我写SerialServer即串口转网口程序的时候,串口通讯的类是从网上Download的一个CSerailPort类,这是个老外在1997年写的一个类,当然在2012年有人修改过了,处理过一些bug。但是比较困扰我的是,它接收到数据是一个char(一个字节)读取的,这导致我写的日志里面都是这个样子的:abcd..._cserialport接收字符

reactor模型实现_c++ reactor模型-程序员宅基地

文章浏览阅读734次。文章目录前言一、什么是reactor模型二、使用步骤1.声明一个reactor结构体2.事件的设置,添加,以及删除2.read,write,accept的事件的处理回调函数3.初始化reactor4.将监听fd加入到reactor5.等待事件6.主函数三、代码解读总结前言对于一个服务器而言:网络 IO通常会涉及到两个系统对象,一个是用户空间的调用IO的进程或者线程,另一个是内核空间。比如发生IO操作的read时,通常会经历两个阶段:等待数据准备就绪,将数据从内核空间拷贝到用户的进程或者线程中。所以多种_c++ reactor模型

随便推点

15、system V 与 posix 信号量的简单比较-程序员宅基地

文章浏览阅读52次。1、XSI system V的信号量是信号量集,可以包括多个信号灯(有个数组),每个操作可以同时操作多个信号灯 posix是单个信号灯,POSIX有名信号灯支持进程间通信,无名信号灯放在共享内存中时可以用于进程间通信。 2、POSIX信号量在有些平台并没有被实现,比如:SUSE8,而SYSTEM V大多数LINUX/UNIX都已经实现。两者都可以用于进程和线程间通信。 3、..._posix信号量和systemv优缺点

在 Ubuntu 20.04 LTS 桌面版上安装 MS 字体_ms字体-程序员宅基地

文章浏览阅读1w次。在 Ubuntu 18.04 LTS 桌面版上安装 MS 字体如下所示安装 MS TrueType 字体:$ sudo apt update $ sudo apt install ttf-mscorefonts-installer然后将会出现 Microsoft 的最终用户协议向导,点击OK以继续。点击Yes已接受 Microsoft 的协议:安装字体之后, 我..._ms字体

大数据GP_gp大数据-程序员宅基地

文章浏览阅读1.9k次。大数据学习成长之路_gp大数据

考研高考化,计算机408备考如何规划?-程序员宅基地

文章浏览阅读592次,点赞14次,收藏23次。在专业课方面,我一直在不断地做真题,并反复看王道讲义上的错题。此时,大家也需要回归到课本,

Python+requests 之GET请求_requestes get请求 python-程序员宅基地

文章浏览阅读1.5w次。1.配置环境安装requests包:python -m pip install requests2.发送GET请求import requestsr = requests.get("http://httpbin.org/get")3. 添加headler和cookiesimport requestsheader = { "User-Agent": "Mozilla/5..._requestes get请求 python

搭建wamp+sqli-labs教程win10虚拟机2021/4/2_sqli wamp安装-程序员宅基地

文章浏览阅读469次。wamp安装下载wamp,没啥好说的,在官网下载,我看也有人用phpstudy,都可wamp官网安装过程中遇到报错msvcr120.dll报错查询原因,缺少VC++环境,下载了VC++运行库集合,一步到位,但是我提供的链接有捆绑软件,大家注意,大街也可以到微软官网网站自行下载。VC++运行库集合安装完成后wamp启动正常sqli-labs安装在github下载下载地址在下载过程中出现github进不去的问题。进入chinaz.com进行检测,哪个节点最快,进行复制到hosts文件目_sqli wamp安装

推荐文章

热门文章

相关标签