如何在C语言代码中为WebSocket连接添加Node-RED的Socket路径
给Node-RED WebSocket服务器添加路径的C代码改造方案
老哥,你现在的问题本质是:原来的C代码只是建立了普通TCP连接直接发数据,但Node-RED的WebSocket是基于HTTP协议升级的通信方式,必须先完成WebSocket握手流程,同时把你需要的/pathofsocket路径嵌入到握手请求里,之后还要按照WebSocket的帧格式发送数据,不然Node-RED的WebSocket节点根本认不出你的请求。
下面直接给你修改后的完整代码,每一步都给你注释清楚:
#include<stdio.h> #include<string.h> #include<sys/socket.h> #include<arpa/inet.h> #include<unistd.h> // 生成WebSocket握手需要的随机key(这里用一个测试用的固定值,生产环境建议随机生成) #define WEBSOCKET_KEY "dGhlIHNhbXBsZSBub25jZQ==" int main(int argc , char *argv[]) { int socket_desc; struct sockaddr_in server; char handshake_request[1024]; char server_reply[2000]; const char* myIpaddr = "你的IP地址"; // 替换成你的Node-RED服务器IP const char* ws_path = "/pathofsocket"; // 你要指定的WebSocket路径 // 创建TCP socket socket_desc = socket(AF_INET , SOCK_STREAM , 0); if (socket_desc == -1) { printf("Could not create socket"); return 1; } // 设置服务器信息 server.sin_addr.s_addr = inet_addr(myIpaddr); server.sin_family = AF_INET; server.sin_port = htons(1880); // 连接服务器 if(connect(socket_desc , (struct sockaddr *)&server , sizeof(server)) < 0) { puts("connect error"); close(socket_desc); return 1; } puts("Connected to TCP server\n"); // 构造WebSocket握手请求,这里关键是把路径放到GET请求里 snprintf(handshake_request, sizeof(handshake_request), "GET %s HTTP/1.1\r\n" "Host: %s:1880\r\n" "Upgrade: websocket\r\n" "Connection: Upgrade\r\n" "Sec-WebSocket-Key: %s\r\n" "Sec-WebSocket-Version: 13\r\n\r\n", ws_path, myIpaddr, WEBSOCKET_KEY); // 发送握手请求 if(send(socket_desc, handshake_request, strlen(handshake_request), 0) < 0) { puts("Handshake send failed"); close(socket_desc); return 1; } puts("WebSocket handshake request sent\n"); // 接收服务器的握手响应,确认是否升级成功 ssize_t recv_len = recv(socket_desc, server_reply, sizeof(server_reply)-1, 0); if(recv_len < 0) { puts("Handshake recv failed"); close(socket_desc); return 1; } server_reply[recv_len] = '\0'; puts("Handshake reply received:\n"); puts(server_reply); // 检查响应是否包含101 Switching Protocols,确认握手成功 if(strstr(server_reply, "101 Switching Protocols") == NULL) { puts("WebSocket handshake failed!"); close(socket_desc); return 1; } puts("\nWebSocket handshake success!\n"); // 准备要发送的传感器数据,需要封装成WebSocket帧格式 char* sensor_data = "SensorDataTest"; int data_len = strlen(sensor_data); char ws_frame[1024]; int frame_pos = 0; // WebSocket帧头构造:FIN=1,Opcode=1(文本帧) ws_frame[frame_pos++] = 0x81; // 负载长度:如果小于126直接写,这里数据短直接用 if(data_len < 126) { ws_frame[frame_pos++] = data_len; } // 复制数据到帧里 memcpy(ws_frame + frame_pos, sensor_data, data_len); frame_pos += data_len; // 发送封装后的WebSocket帧 if(send(socket_desc, ws_frame, frame_pos, 0) < 0) { puts("Sensor data send failed"); close(socket_desc); return 1; } puts("Sensor data sent via WebSocket\n"); // (可选)接收服务器的响应帧,需要解析WebSocket帧格式,这里简化处理 memset(server_reply, 0, sizeof(server_reply)); recv_len = recv(socket_desc, server_reply, sizeof(server_reply)-1, 0); if(recv_len > 0) { puts("Received server reply frame:\n"); // 简单提取文本内容(跳过帧头,假设是文本帧且长度<126) if(server_reply[0] == 0x81 && server_reply[1] < 126) { puts(server_reply + 2); } } close(socket_desc); return 0; }
关键要点解释:
- 握手请求里的路径:在构造
GET请求时,把%s替换成你的/pathofsocket,这就是Node-RED里需要匹配的路径。 - WebSocket协议要求:必须发送包含
Upgrade: websocket、Sec-WebSocket-Key等头的HTTP请求,服务器返回101 Switching Protocols才代表握手成功。 - 数据帧封装:WebSocket不能直接发明文,必须把数据封装成帧格式(代码里处理了最简单的文本帧情况,适合你的测试场景)。
Node-RED那边的配置注意:
你的WebSocket-in节点要设置成:
- 类型:
ws - 路径:
/pathofsocket - 端口:
1880
这样才能和C代码的请求匹配上。
内容的提问来源于stack exchange,提问作者kml2019
相关产品推荐
相关产品推荐

