ssl_write

TCP + OPENSSL

前言

关于TCP/IP和OPENSSL相关的描述我想很多人都知道,这里也不做什么陈述,如果刚接触的话可以去搜搜相关的文章,有很多写的不错的例子让你来更充分地了解他们。

这里的示例是由于要用到TLS1.2协议中的AEAD模式。

话不多说,直接上代码。。。

TCP封装

int setup_tcp_connect(char *ip, char *port)
{
    struct sockaddr_in sin;
    int sockfd;
    int res;
    struct timeval timeout = {60,0};
    int buflen = DEVICE_INFO_ARRAY_MAX_SIZE*240;   //这里我设置了240K的发送缓冲区大小

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    memset(&sin, 0, sizeof(struct sockaddr_in));

    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = inet_addr(ip);
    sin.sin_port = htons(atoi(port));

    if(connect(sockfd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
        printf("[%s:%d] Socket connect error!error msg == %s\n", __FUNCTION__, __LINE__, strerror(errno));
        close(sockfd);
        return -1;
    }

    if(setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(timeout)) < 0) {
        printf("[%s:%d] Setsockopt send timeout fail\n", __FUNCTION__, __LINE__);
        return -1;
    }

    if(setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&buflen, 4) < 0) {
        printf("[%s:%d] Setsockopt sendbuffer fail\n", __FUNCTION__, __LINE__);
        return -1;
    }

    if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout)) < 0) {
        printf("[%s:%d] Setsockopt rcv fail\n", __FUNCTION__, __LINE__);
        return -1;
    }


    printf("[%s:%d] TCP connect success\n", __FUNCTION__, __LINE__);
    return sockfd;
}

SSL封装

SSL *setup_ssl_connect(int sockfd, SSL_CTX *pssl_ctx)
{
    const char *cipher_list = "ECDHE-ECDSA-AES128-GCM-SHA256";    //这里的cipher_list是与服务器协商好的加密套件,这里以其中一个为例
    SSL_METHOD *meth = NULL;
    SSL *pssl = NULL;
    int len = 0;
    int seed_init[DEVICE_INFO_ARRAY_SIZE] = {0};

    OpenSSL_add_ssl_algorithms();
    SSL_load_error_strings();

    meth = (SSL_METHOD *)TLSv1_2_client_method();
    pssl_ctx = SSL_CTX_new(meth);
    if(pssl_ctx == NULL) {
        printf("[%s:%d] SSL CTX NEW error!\n", __FUNCTION__, __LINE__);
        ERR_print_errors_fp(stderr);
        return NULL;
    }

    srand((unsigned)time(NULL));
    for(len = 0; len < 100; len++) {
        seed_init[len] = rand();
    }
    
    RAND_seed(seed_init, sizeof(seed_init));
    SSL_CTX_set_cipher_list(pssl_ctx, cipher_list);
    SSL_CTX_set_mode(pssl_ctx, SSL_MODE_AUTO_RETRY);

    //setup ssl
    pssl = SSL_new(pssl_ctx);
    if(SSL_set_fd(pssl, sockfd) <= 0) {
        printf("[%s:%d] SSL set fd error\n", __FUNCTION__, __LINE__);
        goto error;
    }
    
    SSL_set_mode(pssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);

    if(SSL_connect(pssl) <= 0) {
        printf("[%s:%d] SSL connect error\n", __FUNCTION__, __LINE__);
        ERR_print_errors_fp(stderr);
        goto error;
    }
    printf("[%s:%d] SSL connect success\n", __FUNCTION__, __LINE__);
    return pssl;
error:
    if(SSL_shutdown(pssl) != 1) {
        SSL_shutdown(pssl);
    }
    SSL_free(pssl);
    SSL_CTX_free(pssl_ctx);
    return NULL;
}

int send_requset(char *request_data, long int len, SSL *pssl)
{
    int ret,res;
    long int count = 0;
    
    if(pssl != NULL && request_data != NULL && len > 0) {
    	pthread_mutex_lock(&write_lock);
        while(1) {
            res = SSL_write(pssl, (void *)request_data + count, len - count);
            ret = SSL_get_error(pssl, res);
            if(ret == SSL_ERROR_NONE) {
                if(res > 0) {
                    count += res;
                    if(count >= len) {
                        break;
                    }
                    continue;
                } else {
                    printf("[%s:%d] SSL write error\n", __FUNCTION__, __LINE__);
                    ERR_print_errors_fp(stderr);
                }
            } else if(ret == SSL_ERROR_WANT_READ) {
                continue;
            } else if(ret == SSL_ERROR_WANT_WRITE) {
                continue;
            } else {
                printf("[%s:%d] SSL write error, error code == %d\n", __FUNCTION__, __LINE__, ret);
                ERR_print_errors_fp(stderr);
                break;
            }
        }
        pthread_mutex_unlock(&write_lock);
        return count;
    } else {
        printf("[%s:%d] Send request pssl/request_data/len is NULL\n", __FUNCTION__, __LINE__);
        return -1;
    }
}

备注:按道理这里的ssl_write是不需要加锁的,不过这个是按照自己这边的项目情况而定,没有什么特殊的设定的话不需要加锁

之前在网上也有搜到ssl_write的返回值代表什么意思,这里推荐给大家:
点击这里查看

关于这两个的代码就是这些,下一篇再说ssl_read的相关实现。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值