You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用GnuTLS库建立HTTPS连接时握手触发TLS致命警报问题

问题分析与修复方案

你的代码核心问题出在IPv4地址的字节顺序错误,导致连接到了错误的服务器,进而握手失败,以下是具体说明和修复方案:

1. 核心错误:IP字节序颠倒

你手动构造的IP地址为(7u << 24u) | (32u << 16u) | (18u << 8u) | 104u,但实际解析出的104.18.32.7是主机字节序,转换为网络字节序(大端)时,需要将最高位字节放在最左侧:

  • 正确的网络字节序IP构造应为:(104u << 24u) | (18u << 16u) | (32u << 8u) | 7u
  • 当前写法相当于把IP写成了7.32.18.104,并非Stack Overflow的真实服务IP,连接到错误服务器后,握手自然会触发TLS致命警报。

2. 额外优化建议

  • 避免硬编码IP:推荐使用getaddrinfo动态解析域名,既能避免IP变更问题,也能自动处理字节序转换
  • 完善错误处理:原代码中错误发生时直接返回0,没有输出具体错误信息,建议添加perror或gnutls_strerror打印错误,方便调试
  • 清理资源:程序结束前记得关闭socket和GNUTLS会话,避免资源泄漏

修复后的代码示例

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <gnutls/gnutls.h>
#include <string.h>
#include <unistd.h>

int main ()
{
    int Result_d, SocketFileDescriptor;
    gnutls_session_t GnutlsSession;
    struct sockaddr_in SockAddr;
    
    SocketFileDescriptor = socket (AF_INET, SOCK_STREAM, 0);
    if (SocketFileDescriptor == -1)
    {
        perror("socket creation failed");
        return 1;
    }
    
    SockAddr.sin_family = AF_INET;
    SockAddr.sin_port = htons (443u);
    // 修复IP字节序:正确对应104.18.32.7的网络字节序
    SockAddr.sin_addr.s_addr = (104u << 24u) | (18u << 16u) | (32u << 8u) | 7u;
    Result_d = connect (SocketFileDescriptor, (struct sockaddr *) &SockAddr, sizeof (SockAddr));
    if (Result_d != 0)
    {
        perror("connect failed");
        close(SocketFileDescriptor);
        return 1;
    }
    
    Result_d = gnutls_init (&GnutlsSession, GNUTLS_CLIENT);
    if (Result_d != GNUTLS_E_SUCCESS)
    {
        fprintf(stderr, "gnutls_init failed: %s\n", gnutls_strerror(Result_d));
        close(SocketFileDescriptor);
        return 1;
    }
    
    Result_d = gnutls_set_default_priority (GnutlsSession);
    if (Result_d != GNUTLS_E_SUCCESS)
    {
        fprintf(stderr, "gnutls_set_default_priority failed: %s\n", gnutls_strerror(Result_d));
        gnutls_deinit(GnutlsSession);
        close(SocketFileDescriptor);
        return 1;
    }
    
    gnutls_transport_set_int (GnutlsSession, SocketFileDescriptor);
    
    // "stackoverflow.com"长度为17,此处参数正确
    Result_d = gnutls_server_name_set (GnutlsSession, GNUTLS_NAME_DNS, "stackoverflow.com", 17u);
    if (Result_d != GNUTLS_E_SUCCESS)
    {
        fprintf(stderr, "gnutls_server_name_set failed: %s\n", gnutls_strerror(Result_d));
        gnutls_deinit(GnutlsSession);
        close(SocketFileDescriptor);
        return 1;
    }
    
    Result_d = gnutls_handshake (GnutlsSession);
    if (Result_d != GNUTLS_E_SUCCESS)
    {
        fprintf (stderr, "gnutls_handshake() returned: %s\n", gnutls_strerror (Result_d));
        gnutls_deinit(GnutlsSession);
        close(SocketFileDescriptor);
        return 1;
    }

    printf("TLS handshake successful!\n");

    // 清理资源
    gnutls_deinit(GnutlsSession);
    close(SocketFileDescriptor);
    
    return 0;
}

内容的提问来源于stack exchange,提问作者Kolodez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 20:53:21