select ssl_pending ssl_read 阻塞模型读应用数据,代码举例
时间: 2024-02-20 21:58:38 浏览: 241
下面是一个基于阻塞模型的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。
阅读全文