#include <stdio.h>          // 引入标准输入输出库,用于printf等函数
#include <stdlib.h>         // 引入标准库,用于内存分配、程序退出等功能
#include <string.h>         // 引入字符串处理库,用于字符串操作函数
#include <unistd.h>         // 引入Unix标准库,提供read、write、close等系统调用
#include <arpa/inet.h>      // 引入网络地址转换库,提供IP地址转换等功能

#define PORT 11434          // 定义服务器端口号(Ollama默认端口)
#define SERVER_IP "172.20.10.6"   // 定义目标服务器的IP地址
#define BUFFER_SIZE 4096 * 10    // 定义接收缓冲区大小为40KB

int main(int argc, char const *argv[])  // 主函数,argc为参数数量,argv为参数数组
{

    if (argc != 2)                      // 检查命令行参数是否为2个(程序名+提示词)
    {
        printf("Usage: %s <prompt>\n", argv[0]);  // 打印程序正确使用方法
        return 1;                       // 参数错误,返回1退出程序
    }

    int sock = 0;                       // 声明socket文件描述符并初始化
    struct sockaddr_in serv_addr;       // 声明服务器地址结构体
    char buffer[BUFFER_SIZE] = {0};     // 声明接收缓冲区并初始化为0

    // 创建TCP socket:AF_INET(IPv4),SOCK_STREAM(TCP),0(默认协议)
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("\n Socket creation error \n");  // 打印socket创建失败信息
        return -1;                       // 创建失败,返回-1退出
    }

    serv_addr.sin_family = AF_INET;     // 设置地址族为IPv4
    serv_addr.sin_port = htons(PORT);   // 将端口号转换为网络字节序(大端模式)

    // 将字符串形式的IP地址转换为二进制格式,存储到服务器地址结构体
    if (inet_pton(AF_INET, SERVER_IP, &serv_addr.sin_addr) <= 0)
    {
        printf("\nInvalid address/ Address not supported \n");  // 打印地址无效信息
        return -1;                       // 地址错误,返回-1退出
    }

    // 连接到服务器,参数为socket描述符、服务器地址结构体、结构体大小
    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    {
        printf("\nConnection Failed \n");  // 打印连接失败信息
        return -1;                       // 连接失败,返回-1退出
    }

    // 声明并初始化HTTP请求体缓冲区
    char request_body[1024] = {0};

    // 格式化构造JSON请求体,包含模型名称、提示词和其他参数
    snprintf(request_body, 1024, "{\"model\": \"deepseek-r1:1.5b\", \"prompt\": \"%s\", \"stream\": false,\"include_context\": false}", argv[1]);

    // 声明HTTP请求头缓冲区
    char request_headers[256] = {0};
    // 格式化构造HTTP请求头,包含请求方法、路径、主机、内容类型和长度
    snprintf(request_headers, sizeof(request_headers),
             "POST /api/generate HTTP/1.1\r\n"
             "Host: 192.168.128.196:11434\r\n"
             "Content-Type: application/json\r\n"
             "Content-Length: %zu\r\n"
             "\r\n",
             strlen(request_body));

    // 声明完整HTTP请求缓冲区
    char request[4096] = {0};
    // 将请求头和请求体组合成完整的HTTP请求
    snprintf(request, sizeof(request), "%s%s", request_headers, request_body);

    // 发送HTTP请求到服务器
    send(sock, request, strlen(request), 0);
    printf("Request sent:\n%s\n", request);  // 打印已发送的请求内容

    while (1)  // 无限循环接收服务器响应
    {
        // 从socket读取响应数据到缓冲区
        int valread = read(sock, buffer, BUFFER_SIZE);
        if (valread > 0)  // 成功读取到数据
        {
            printf("Response:\n%s\n", buffer);  // 打印接收到的响应内容
        }
        else  // 读取失败或连接关闭
        {
            printf("Failed to receive response.\n");  // 打印接收失败信息
        }
    }

    // 关闭socket连接(注:由于上面是无限循环,此行实际不会执行)
    close(sock);
    return 0;  // 程序正常退出
}

这段代码是一个 C 语言编写的客户端程序,用于通过 HTTP 协议与指定服务器上的 API 进行通信,具体来说是发送请求到一个类似 Ollama 的大语言模型 API 并接收响应。

让我为你详细解释代码的各个部分:

  1. 头文件和宏定义

    • 包含了网络编程、输入输出、字符串处理等必要的头文件
    • 定义了端口号PORT为 11434(这是 Ollama 默认使用的端口)
    • 定义了服务器 IP 地址SERVER_IP
    • 定义了缓冲区大小BUFFER_SIZE
  2. 参数检查

    • 检查程序运行时是否提供了一个命令行参数(prompt 内容)
    • 如果参数数量不对,打印使用方法并退出
  3. Socket 创建与初始化

    • 创建一个 TCP socket(SOCK_STREAM
    • 设置服务器地址结构,包括地址族、端口号
    • 将服务器 IP 地址从字符串转换为二进制格式
  4. 连接服务器

    • 使用connect函数尝试连接到指定的服务器和端口
    • 如果连接失败,打印错误信息并退出
  5. 构造 HTTP 请求

    • 构造请求体(JSON 格式),包含模型名称(deepseek-r1:1.5b)、提示词(从命令行参数获取)和其他参数
    • 构造 HTTP 请求头,包含请求方法(POST)、目标路径(/api/generate)、主机地址、内容类型和内容长度
    • 将请求头和请求体组合成完整的 HTTP 请求
  6. 发送请求与接收响应

    • 使用send函数发送 HTTP 请求到服务器
    • 进入循环,使用read函数持续接收服务器的响应数据
    • 每次接收到数据后,将其打印出来
    • 注意:这段代码的循环没有退出条件,会一直运行直到程序被强制终止
  7. 关闭连接

    • 关闭 socket 连接(虽然在当前代码中因为循环没有退出条件,这行代码实际上永远不会被执行)

简单来说,这个程序的作用是:运行时接收一个提示词作为参数,然后向指定 IP 和端口的大语言模型 API 发送请求,获取模型的生成结果并打印出来。这类似于通过命令行调用 AI 模型进行问答。

编辑分享

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐