ssl_pending
时间: 2023-07-02 08:08:34 浏览: 317
`ssl_pending` 是一个函数,用于查询 SSL/TLS 报文的缓冲区中是否有未读数据。该函数通常用于非阻塞 I/O 操作中,以确定是否有足够的数据可供读取而无需阻塞线程。在 OpenSSL 库中,该函数的原型如下:
```c
int SSL_pending(const SSL *ssl);
```
该函数的参数为一个 SSL 对象的指针,返回值为当前 SSL 对象待读取的字节数。如果返回值为 0,则表示当前没有未读数据;如果返回值大于 0,则表示当前有未读数据。
相关问题
select ssl_pending ssl_read 阻塞模型读应用数据,代码举例
下面是一个基于阻塞模型的SSL连接读取应用数据的示例代码,使用了select函数来检测是否有可读数据和是否有未处理的SSL数据:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <errno.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#define SERVER_ADDR "127.0.0.1"
#define SERVER_PORT 8080
int main(int argc, char **argv) {
int sockfd, ret;
struct sockaddr_in server_addr;
char buf[1024];
fd_set rfds;
struct timeval tv;
SSL_CTX *ctx;
SSL *ssl;
// 创建socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("socket");
return -1;
}
// 设置服务器地址
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(SERVER_ADDR);
server_addr.sin_port = htons(SERVER_PORT);
// 连接服务器
ret = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret < 0) {
perror("connect");
return -1;
}
// 初始化SSL
SSL_library_init();
ctx = SSL_CTX_new(SSLv23_client_method());
if (ctx == NULL) {
perror("SSL_CTX_new");
return -1;
}
ssl = SSL_new(ctx);
SSL_set_fd(ssl, sockfd);
SSL_connect(ssl);
// 从服务器读取数据并发送应答
while (1) {
FD_ZERO(&rfds);
FD_SET(sockfd, &rfds);
tv.tv_sec = 5;
tv.tv_usec = 0;
ret = select(sockfd + 1, &rfds, NULL, NULL, &tv);
if (ret < 0) {
perror("select");
break;
} else if (ret == 0) {
printf("timeout\n");
continue;
} else {
if (FD_ISSET(sockfd, &rfds)) {
ret = SSL_read(ssl, buf, sizeof(buf));
if (ret < 0) {
perror("SSL_read");
break;
} else if (ret == 0) {
printf("connection closed by server\n");
break;
} else {
// 处理收到的数据
printf("received %d bytes: %.*s\n", ret, ret, buf);
// 发送应答数据
SSL_write(ssl, "ACK", 3);
}
}
}
}
// 关闭SSL连接
SSL_shutdown(ssl);
SSL_free(ssl);
SSL_CTX_free(ctx);
// 关闭socket
close(sockfd);
return 0;
}
```
这个示例代码中使用了select函数来等待可读数据,然后使用SSL_read函数读取SSL数据,如果有未处理的SSL数据,就使用ssl_pending函数来检测。如果读取成功,则对收到的数据进行处理,并使用SSL_write函数发送应答数据。如果发生错误,就退出循环并关闭SSL连接和socket。
在阻塞模型中,如果select读取有数据的socket,但是在使用ssl_read读取数据时返回-1,可以使用SSL_pending函数来检查SSL连接中是否有数据可供读取。如果SSL_pending返回大于0的值,则可以使用SSL_read函数来读取剩余的数据.代码实现
可以使用以下代码来实现使用SSL_pending函数来检查SSL连接中是否有数据可供读取,如果有,则使用SSL_read函数读取剩余的数据:
```c
int ret;
while ((ret = SSL_read(ssl, buf, len)) <= 0) {
if (SSL_get_error(ssl, ret) == SSL_ERROR_WANT_READ) {
/* 等待更多数据可用 */
continue;
}
if (SSL_pending(ssl) > 0) {
/* 读取剩余的数据 */
ret = SSL_read(ssl, buf + ret, len - ret);
break;
}
/* 处理其他错误 */
break;
}
```
这里使用了一个循环,如果SSL_read返回SSL_ERROR_WANT_READ错误,则继续等待更多的数据可用。如果SSL_pending返回大于0的值,则读取剩余的数据。如果有其他错误,则退出循环并进行适当的错误处理。
需要注意的是,SSL_pending只能用于非阻塞模式下的SSL连接,如果使用阻塞模式,则SSL_pending永远返回0。
阅读全文