以下是使用 jQuery 实现 WebSocket 连接的基本示例代码:
// 声明 websocket 变量
var webSocket;
// 与服务器建立连接
function connect() {
webSocket = new WebSocket("ws://localhost:8080");
// 连接成功时触发的事件
webSocket.onopen = function(event) {
console.log("WebSocket连接已建立");
};
// 接收到消息时触发的事件
webSocket.onmessage = function(event) {
console.log("接收到消息:" + event.data);
};
// 连接关闭时触发的事件
webSocket.onclose = function(event) {
console.log("WebSocket连接已关闭");
};
// 发生错误时触发的事件
webSocket.onerror = function(event) {
console.log("WebSocket连接发生错误");
};
}
// 向服务器发送消息
function sendMsg() {
var msg = $("#msg").val();
webSocket.send(msg);
}
// 关闭 WebSocket 连接
function closeWebSocket() {
webSocket.close();
}
// 初始化函数
$(document).ready(function() {
$("#connectBtn").click(function() {
connect();
});
$("#sendBtn").click(function() {
sendMsg();
});
$("#closeBtn").click(function() {
closeWebSocket();
});
});
上述代码中,我们声明了 webSocket
变量用来保存 WebSocket 连接对象,然后定义了 connect()
、sendMsg()
和 closeWebSocket()
三个方法分别用来建立连接、发送消息和关闭连接。在初始化函数中,我们使用 jQuery 的 click()
方法来绑定按钮的点击事件,然后分别调用上述三个方法。
需要注意的是,以上代码仅为示例代码,实际使用时需要根据具体情况进行修改。在使用 WebSocket 通信时,还需要注意跨域访问等问题。
以下是使用C语言实现嵌入式设备开发websocket的示例代码,该代码为设备端作为server端与网页进行交互:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
// 定义websocket协议的一些常量
#define WS_MAGIC "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
#define WS_HEADER_LEN 2
#define WS_MASK_LEN 4
#define WS_FIN_BIT 0x80
#define WS_OPCODE_MASK 0x0f
#define WS_MASK_BIT 0x80
#define WS_PAYLOAD_LEN_MASK 0x7f
// websocket帧类型
enum ws_opcode {
WS_OPCODE_CONTINUATION = 0x0,
WS_OPCODE_TEXT = 0x1,
WS_OPCODE_BINARY = 0x2,
WS_OPCODE_CLOSE = 0x8,
WS_OPCODE_PING = 0x9,
WS_OPCODE_PONG = 0xa
};
// 创建websocket连接并进行握手
int ws_connect(char *address, int port)
{
// 创建TCP套接字
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
perror("socket");
return -1;
}
// 设置套接字选项
int flags = fcntl(sockfd, F_GETFL, 0);
if (flags == -1) {
close(sockfd);
perror("fcntl");
return -1;
}
if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) == -1) {
close(sockfd);
perror("fcntl");
return -1;
}
// 构造连接地址
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(address);
addr.sin_port = htons(port);
// 连接到服务器
int ret = connect(sockfd, (struct sockaddr *)&addr, sizeof(addr));
if (ret == -1 && errno != EINPROGRESS) {
close(sockfd);
perror("connect");
return -1;
}
// 等待连接完成
fd_set write_fds;
FD_ZERO(&write_fds);
FD_SET(sockfd, &write_fds);
ret = select(sockfd + 1, NULL, &write_fds, NULL, NULL);
if (ret == -1) {
close(sockfd);
perror("select");
return -1;
}
// 检查连接是否成功
int error = 0;
socklen_t len = sizeof(error);
if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) == -1 || error != 0) {
close(sockfd);
perror("getsockopt");
return -1;
}
// 发送握手请求
char request[1024];
snprintf(request, sizeof(request), "GET / HTTP/1.1\r\n"
"Upgrade: websocket\r\n"
"Connection: Upgrade\r\n"
"Sec-WebSocket-Version: 13\r\n"
"Host: %s:%d\r\n"
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
"\r\n",
address, port);
ret = write(sockfd, request, strlen(request));
if (ret == -1) {
close(sockfd);
perror("write");
return -1;
}
// 读取握手响应
char response[1024];
ret = read(sockfd, response, sizeof(response) - 1);
if (ret == -1) {
close(sockfd);
perror("read");
return -1;
}
response[ret] = '\0';
// 解析握手响应
char *p = strstr(response, "\r\n\r\n") + 4;
char buf[1024];
snprintf(buf, sizeof(buf), "%s%s", p, WS_MAGIC);
char sha1[20];
mbedtls_sha1((const unsigned char *)buf, strlen(buf), (unsigned char *)sha1);
char output[sizeof(sha1) * 2 + 1];
for(int i = 0; i < sizeof(sha1); i++) {
sprintf(output + i * 2, "%02x", sha1[i]);
}
// 发送握手响应
char handshake[1024];
snprintf(handshake, sizeof(handshake), "HTTP/1.1 101 Switching Protocols\r\n"
"Upgrade: websocket\r\n"
"Connection: Upgrade\r\n"
"Sec-WebSocket-Accept: %s\r\n"
"\r\n",
output);
ret = write(sockfd, handshake, strlen(handshake));
if (ret == -1) {
close(sockfd);
perror("write");
return -1;
}
return sockfd;
}
// 发送websocket数据帧
int ws_send(int sockfd, enum ws_opcode opcode, char *data, int len)
{
// 构造websocket头部
unsigned char header[14];
memset(header, 0, 14);
header[0] = WS_FIN_BIT | opcode;
if (len < 126) {
header[1] = len | WS_MASK_BIT;
header[2] = 0x01; // 随机生成掩码
header[3] = 0x02; // 随机生成掩码
header[4] = 0x03; // 随机生成掩码
header[5] = 0x04; // 随机生成掩码
} else if (len < 65536) {
header[1] = 0x7e | WS_MASK_BIT;
header[2] = (len >> 8) & 0xff;
header[3] = len & 0xff;
header[4] = 0x01; // 随机生成掩码
header[5] = 0x02; // 随机生成掩码
header[6] = 0x03; // 随机生成掩码
header[7] = 0x04; // 随机生成掩码
} else {
header[1] = 0x7f | WS_MASK_BIT;
header[2] = (len >> 56) & 0xff;
header[3] = (len >> 48) & 0xff;
header[4] = (len >> 40) & 0xff;
header[5] = (len >> 32) & 0xff;
header[6] = (len >> 24) & 0xff;
header[7] = (len >> 16) & 0xff;
header[8] = (len >> 8) & 0xff;
header[9] = len & 0xff;
header[10] = 0x01; // 随机生成掩码
header[11] = 0x02; // 随机生成掩码
header[12] = 0x03; // 随机生成掩码
header[13] = 0x04; // 随机生成掩码
}
// 发送websocket数据帧
int ret = write(sockfd, header, WS_HEADER_LEN + WS_MASK_LEN);
if (ret == -1) {
close(sockfd);
perror("write");
return -1;
}
ret = write(sockfd, data, len);
if (ret == -1) {
close(sockfd);
perror("write");
return -1;
}
return 0;
}
// 接收websocket数据帧
int ws_recv(int sockfd, enum ws_opcode *opcode, char **data, int *len)
{
// 读取websocket头部
unsigned char header[14];
memset(header, 0, 14);
int ret = read(sockfd, header, WS_HEADER_LEN);
if (ret == -1) {
close(sockfd);
perror("read");
return -1;
}
if (ret == 0) {
close(sockfd);
return -1;
}
if (!(header[0] & WS_FIN_BIT)) {
printf("fragmented frame received\n");
return -1;
}
*opcode = header[0] & WS_OPCODE_MASK;
int has_mask = header[1] & WS_MASK_BIT;
*len = header[1] & WS_PAYLOAD_LEN_MASK;
unsigned char mask[4];
if (has_mask) {
ret = read(sockfd, mask, WS_MASK_LEN);
if (ret == -1) {
close(sockfd);
perror("read");
return -1;
}
}
// 读取websocket数据
char *buf = malloc(*len + 1);
memset(buf, 0, *len + 1);
ret = read(sockfd, buf, *len);
if (ret == -1) {
close(sockfd);
perror("read");
free(buf);
return -1;
}
if (ret != *len) {
printf("incomplete frame received\n");
free(buf);
return -1;
}
// 解码websocket数据
if (has_mask) {
for (int i = 0; i < *len; i++) {
buf[i] ^= mask[i % 4];
}
}
*data = buf;
return 0;
}
int main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "Usage: %s <port>\n", argv[0]);
exit(EXIT_FAILURE);
}
int port = atoi(argv[1]);
// 监听端口并等待连接
int sockfd = ws_connect("localhost", port);
if (sockfd == -1) {
perror("ws_connect");
exit(EXIT_FAILURE);
}
printf("Connected to server\n");
while (1) {
// 接收websocket数据帧
enum ws_opcode opcode;
char *data = NULL;
int len;
int ret = ws_recv(sockfd, &opcode, &data, &len);
if (ret == -1) {
perror("ws_recv");
exit(EXIT_FAILURE);
}
// 处理websocket数据帧
switch (opcode) {
case WS_OPCODE_TEXT:
printf("Recv text: %s\n", data);
// 发送回应
ws_send(sockfd, WS_OPCODE_TEXT, data, len);
break;
case WS_OPCODE_BINARY:
printf("Recv binary data with length %d\n", len);
// 发送回应
ws_send(sockfd, WS_OPCODE_BINARY, data, len);
break;
case WS_OPCODE_CLOSE:
printf("Recv close frame\n");
// 发送关闭响应并退出循环
ws_send(sockfd, WS_OPCODE_CLOSE, NULL, 0);
goto exit_loop;
default:
printf("Invalid opcode %d\n", opcode);
break;
}
free(data);
}
exit_loop:
close(sockfd);
return EXIT_SUCCESS;
}
该示例代码实现了一个简单的websocket server,它监听指定的端口并等待客户端连接,对于接收到的不同类型的websocket数据帧作出回应。你可以运行该程序,然后在网页中使用JavaScript编写websocket client并与之交互。