使用LibCurl通过Telnet控制投影仪遇未知选项错误求助
问题:通过libcurl向Telnet投影仪发送查询命令失败
我有一台支持Telnet通信的投影仪,需要发送命令:POWR ?\r查询电源状态。使用PUTTY操作正常,但用以下libcurl代码执行时出错:
FILE* console = fopen("/dev/tty", "w"); CURL* curl = curl_easy_init(); CURLcode res; if (curl) { CURLcode res; struct curl_slist* options; options = curl_slist_append(NULL, "TTTYPE=:POWR ?\r"); curl_easy_setopt(curl, CURLOPT_URL, "telnet://192.168.0.90"); curl_easy_setopt(curl, CURLOPT_PORT, 1025); curl_easy_setopt(curl, CURLOPT_TELNETOPTIONS, options); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s); res = curl_easy_perform(curl); if (res != CURLE_OK) { fprintf(console, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_easy_cleanup(curl); curl_slist_free_all(options); fprintf(console, s.c_str()); }
执行后错误信息:
curl_easy_perform() failed: An unknown option was passed in to libcurl
我怀疑问题出在这段代码:
struct curl_slist* options; options = curl_slist_append(NULL, "TTTYPE=:POWR ?\r"); curl_easy_setopt(curl, CURLOPT_TELNETOPTIONS, options);
请问如何正确发送命令并获取结果?
解决方案
错误原因
你误用了CURLOPT_TELNETOPTIONS——这个选项是用来配置Telnet协议的内置选项(比如终端类型、窗口大小等),格式为OPTION=VALUE,而TTTYPE并不是合法的Telnet选项,直接把查询命令填在这里会导致libcurl识别失败,抛出"未知选项"错误。
正确实现方式
要通过libcurl向Telnet服务器发送自定义命令,需要利用CURLOPT_READFUNCTION回调函数:libcurl在Telnet会话中会主动调用读回调,获取要发送给服务器的数据。具体步骤如下:
- 定义读回调函数,返回要发送的查询命令
- 通过
CURLOPT_READFUNCTION和CURLOPT_READDATA指定回调逻辑 - 移除错误的
CURLOPT_TELNETOPTIONS配置 - 用
CURLOPT_WRITEFUNCTION回调接收投影仪返回的数据
修改后的完整代码
#include <curl/curl.h> #include <string> #include <cstdio> #include <cstring> // 读回调:向投影仪发送查询命令 size_t telnet_read_callback(char* buffer, size_t size, size_t nitems, void* userdata) { std::string* cmd = static_cast<std::string*>(userdata); if(cmd->empty()) { return 0; // 返回0表示无更多数据发送 } size_t copy_len = std::min(size * nitems, cmd->size()); memcpy(buffer, cmd->data(), copy_len); cmd->erase(0, copy_len); return copy_len; } // 写回调:接收投影仪返回的数据 size_t telnet_write_callback(char* buffer, size_t size, size_t nitems, void* userdata) { std::string* response = static_cast<std::string*>(userdata); response->append(buffer, size * nitems); return size * nitems; } int main() { FILE* console = fopen("/dev/tty", "w"); if(!console) { perror("fopen failed"); return 1; } std::string cmd = ":POWR ?\r"; // 要发送的查询命令 std::string response; // 存储返回结果 CURL* curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "telnet://192.168.0.90"); curl_easy_setopt(curl, CURLOPT_PORT, 1025); // 设置读回调,发送自定义命令 curl_easy_setopt(curl, CURLOPT_READFUNCTION, telnet_read_callback); curl_easy_setopt(curl, CURLOPT_READDATA, &cmd); // 设置写回调,接收返回数据 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, telnet_write_callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); // 执行Telnet会话 CURLcode res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(console, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } else { fprintf(console, "投影仪返回结果:\n%s\n", response.c_str()); } curl_easy_cleanup(curl); } fclose(console); return 0; }
关键说明
- 读回调:当libcurl需要向Telnet服务器发送数据时触发,我们在这里返回预定义的查询命令,发送完成后返回0终止发送。
- 写回调:libcurl接收到投影仪返回的数据时触发,将数据追加到字符串中保存。
- 移除了错误的
CURLOPT_TELNETOPTIONS配置,避免非法选项导致的错误。
测试注意事项
- 确认投影仪的Telnet端口确实是1025,与代码中
CURLOPT_PORT设置一致。 - 命令末尾的
\r必须保留,和PUTTY操作时的格式保持一致。 - 编译时需链接libcurl库,例如GCC编译命令:
g++ -o telnet_projector telnet_projector.cpp -lcurl
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

