SSL_write error! fd:71, len:121798, SSL_get_error=5,
时间: 2024-05-28 18:13:47 浏览: 166
这个错误通常表示在使用 SSL/TLS 加密通信时,写入数据时发生了错误。其中,`fd` 表示文件描述符,`len` 表示写入数据的长度。`SSL_get_error=5` 表示错误码为 `SSL_ERROR_SYSCALL`,意味着在系统调用时发生了错误。
可能的原因包括:
- 网络连接出现问题,例如连接中断、超时等。
- SSL/TLS 握手失败,例如证书验证失败、协议版本不兼容等。
- 写入数据时出现了内部错误。
您可以尝试以下操作来解决这个问题:
- 检查网络连接是否正常,尝试重新连接。
- 检查 SSL/TLS 配置是否正确,包括证书、密码等。
- 检查代码逻辑是否正确,排除写入数据时出现的问题。
相关问题
指出下面代码的问题 运行出现了段错误 #include <openssl/ssl.h> #include <openssl/bio.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <netinet/in.h> #include <netdb.h> #include <sys/socket.h> #include <openssl/err.h> void parse_url(char *url, char *protocol, char *domain, char path) { char ptr; if (strncmp(url, "http://", 7) == 0) { strcpy(protocol, "http"); ptr = url + 7; } else if (strncmp(url, "https://", 8) == 0) { strcpy(protocol, "https"); ptr = url + 8; } else { strcpy(protocol, ""); ptr = url; } char domain_end = strstr(ptr, "/"); if (domain_end == NULL) { strcpy(domain, ptr); strcpy(path, ""); } else { int len = domain_end - ptr; strncpy(domain, ptr, len); domain[len] = '\0'; strcpy(path, domain_end); } } int https_communication(char url, char message, char response) { int sockfd, err; struct sockaddr_in serv_addr; struct hostent *server; SSL_CTX *ctx; SSL *ssl; char buf[1024]; printf("test1111 " ); // 创建socket sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { perror("ERROR opening socket"); return -1; } // 获取主机信息 server = gethostbyname(url); printf("test1111 " ); if (server == NULL) { perror("ERROR, no such host"); return -1; } // 设置服务地址 printf("test1111 " ); bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length); serv_addr.sin_port = htons(443); printf("test222 " ); // 连接服务器 if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) { perror("ERROR connecting"); return -1; } // 初始化SSL SSL_library_init(); ctx = SSL_CTX_new(TLS_method()); if (ctx == NULL) { perror("SSL_CTX_new"); return (-1); } // 设置支持的协议版本为 TLSv1.2 SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION); SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION); //ctx = SSL_CTX_new(TLSv1_2_client_method()); if (ctx == NULL) { perror("ERROR creating SSL context"); return -1; } printf("test1111 " ); // 创建SSL套接字 ssl = SSL_new(ctx); SSL_set_fd(ssl, sockfd); // SSL握手 err = SSL_connect(ssl); if (err < 0) { perror("ERROR performing SSL handshake"); return -1; } printf("test1111 " ); // 发送消息 char request[1024]; sprintf(request, "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", message, url); err = SSL_write(ssl, request, strlen(request)); if (err < 0) { perror("ERROR writing to socket"); return -1; } printf("test1111 " ); // 接收响应 bzero(buf, sizeof(buf)); err = SSL_read(ssl, buf, sizeof(buf)-1); if (err < 0) { perror("ERROR reading from socket"); return -1; } printf("test1111999999999 " ); strcpy(response, buf); // 关闭SSL套接字 SSL_free(ssl); SSL_CTX_free(ctx); // 关闭socket close(sockfd); return 0; } int main() { //char *url = "https://otaapi-sit.lotuscars.com.cn/v50/vehicle/api/register"; //char protocol[10], domain[100], path[1000]; //parse_url(url, protocol, domain, path); //printf("protocol: %s\n", protocol); //printf("domain: %s\n", domain); //printf("path: %s\n", path); char *url = "otaapi-sit.lotuscars.com.cn"; //const char *cert_path="/home/pi/Cdaima/certDHU.pem"; char *payload= "{"timestamp":1685523498,"sdkVersion":"1.0.30_1","vin":"LJUBMSA24PKFFF198","sign":"696c3034f04f2bd80c8929089a0deea8cf4812574b002a555f8af663e500c4ce"}"; char *response=NULL; //https_request(cert_path,payload,url) ; //gethostbyname(url); https_communication(url, payload, response); return 0; } 请给出调用函数的示例
以下是调用 https_communication 函数的示例代码:
```c
int main() {
char *url = "https://otaapi-sit.lotuscars.com.cn/v50/vehicle/api/register";
char message[1024];
char response[1024];
parse_url(url, NULL, message, NULL);
https_communication(url, message, response);
printf("Response: %s\n", response);
return 0;
}
```
需要注意的是,调用 https_communication 函数之前,需要先调用 parse_url 函数解析出 message 参数。另外,在调用 https_communication 函数之后,可以通过 response 参数获取响应内容。
.阻塞模型,select读有数据,ssl_read读取数据返回-1优化代码
针对这种情况,你可以尝试以下优化代码:
1. 在调用ssl_read之前,先检查SSL握手状态,确保握手已经成功完成,否则重新进行握手。
2. 在调用ssl_read之前,先检查SSL会话是否过期,如果过期,可以考虑重新建立SSL会话。
3. 在调用ssl_read之前,先检查网络连接状态,如果连接已经中断,可以考虑进行重连或者其他网络故障处理操作。
4. 在调用ssl_read之前,使用非阻塞模式进行设置,可以避免阻塞。如果ssl_read返回-1并且errno为EAGAIN或EWOULDBLOCK,则可以再次调用select等待数据可读,直到ssl_read返回正确的数据或者出现其他错误。
5. 在代码中加入错误处理代码,避免出现逻辑错误。同时,可以加入日志记录功能,便于排查问题。
示例代码:
```
// 设置非阻塞模式
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
// SSL握手
if (SSL_do_handshake(ssl) != 1) {
int err = SSL_get_error(ssl, ret);
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
// 握手未完成,等待下一次循环
continue;
} else {
// 握手失败,关闭连接
close(fd);
return -1;
}
}
// 检查SSL会话是否过期
if (SSL_session_reused(ssl) == 0) {
// SSL会话过期,重新建立SSL会话
SSL_set_session(ssl, NULL);
SSL_set_fd(ssl, fd);
if (SSL_connect(ssl) != 1) {
close(fd);
return -1;
}
}
// 检查网络连接状态
if (select(fd + 1, &readfds, NULL, NULL, &tv) <= 0) {
// 连接中断,重连或其他处理
close(fd);
return -1;
}
// 读取数据
int nread = 0;
while ((nread = SSL_read(ssl, buf, len)) <= 0) {
int err = SSL_get_error(ssl, nread);
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
// 数据未准备好,等待下一次循环
continue;
} else {
// 其他错误,退出循环
break;
}
}
```
阅读全文