libwebsockets入门

WebSocket是一种在单个TCP连接上进行全双工通讯的协议,用于在Web客户端和服务器之间建立持久连接,进行实时通信。它是HTML5开始提供的一种通讯方式,通过使用WebSocket连接,web应用程序可以执行实时的交互,而不是以前的轮询方式。一个WebSocket连接是独立的TCP连接,异步的、双向的、全双工的消息传递实现机制。

特点

WebSocket具有以下特点:

  • 持久连接:在HTTP协议的基础上,WebSocket实现了长连接,即服务器和客户端之间可以保持长时间的通信状态,避免了频繁建立和断开连接的开销。
  • 全双工通信:WebSocket允许服务器和客户端之间任意时刻发送消息,实现了真正的双向通信。
  • 协议切换:WebSocket协议在HTTP协议的基础上升级实现,兼容性良好,可以在使用同样域名和端口的情况下,升级到WebSocket协议。
  • 轻量级:WebSocket的数据格式比较轻量,性能开销小,通信高效。
  • 跨平台性:WebSocket可以在不同的操作系统和设备上使用,具有较好的跨平台性。
  • 总的来说,WebSocket是一种高效、稳定的网络通信协议,适用于需要实时交互的Web应用程序。

发展简介

WebSocket的历史背景可以追溯到2008年,当时WebSocket协议首次被提出。自2010年开始,WebSocket得到了浏览器厂商的广泛支持,并逐渐成为Web应用程序中实现实时通信的重要技术。在此之前,虽然已经存在一些实时通信技术,但它们通常需要通过入侵现有的web技术来实现,而这些技术并不是为实时应用而设计的。

在WebSocket出现之前,web是建立在HTTP协议的基础上的,而HTTP协议最初完全是作为一种请求-响应机制设计的。这种机制在早期的web应用中表现良好,因为当时的场景只需要处理一个文本文档和一些额外的资源即可。然而,随着web应用的不断发展,对于实时通信的需求也越来越强烈,WebSocket就是在这样的背景下应运而生的。

WebSocket的出现为Internet通信创造了新的可能性,并为真正的实时通讯打开了大门。它提供了一种持久连接的方式,使得服务器和客户端之间可以保持长时间的通信状态,从而实现了真正的双向通信。同时,WebSocket也具有较好的兼容性和跨平台性,可以在不同的操作系统和设备上使用。

总之,WebSocket的历史背景是在web应用程序对于实时通信的需求不断增长的背景下产生的。它提供了一种高效、稳定的网络通信协议,适用于需要实时交互的Web应用程序。

libwebsockets

libwebsockets是一种用于C语言的轻量级网络库,它提供了为创建WebSocket服务器和客户端而编写的API。使用它可以轻松地实现WebSockets、HTTP(S)/1.1等协议。它旨在成为一个高效、灵活和可移植的解决方案。

在这里插入图片描述

现在由意大利的计算机科学家Salvatore Sanfilippo维护,他也是Redis数据库的创建者。

libwebsockets的优点包括:

  • 轻量级:libwebsockets使用C语言编写,不需要任何附加的库或外部依赖项,非常轻量级。
  • 高效性:libwebsockets旨在提供高效性和低消耗,与其他网络库相比,它的消息处理速度更快,内存开销更小。
  • 可移植性:libwebsockets可以在所有主要平台上运行,包括Windows、Linux、Mac OS X等,提供了适用于多个平台的API,且易于移植到其他平台。
  • 支持ws://wss://协议:libwebsockets支持ws://wss://协议,可以选择和OpenSSLCyaSSL或者WolfSSL链接。
  • 事件循环、零拷贝:libwebsockets支持事件循环、零拷贝等功能。
  • API丰富:libwebsockets提供的API相当底层,可以实现简单的功能,对于复杂功能也提供了丰富的API支持。
  • 总之,libwebsockets具有轻量级、高效性、可移植性、支持多种协议、事件循环和零拷贝等特点,是一个功能强大的网络库。

入门示例

这个示例程序创建了一个WebSocket服务器,监听端口号为8000。它使用自定义的协议echo-protocol,当接收到客户端发送的消息时,会将收到的消息原样返回。程序使用lws_create_context创建WebSocket服务器上下文,并使用lws_service处理WebSocket连接。最后,使用lws_context_destroy销毁WebSocket服务器上下文。

#include <libwebsockets.h>  
#include <string.h>  
static int callback_echo(struct lws *wsi, enum lws_callback_reasons reason,  
 void *user, void *in, size_t len) {
	switch (reason) {
		case LWS_CALLBACK_ESTABLISHED: // 当新的连接建立时触发  
		lws_callback_on_writable(wsi);
		break;
		case LWS_CALLBACK_RECEIVE: // 当接收到客户端发送的消息时触发  
		// 直接将收到的消息返回给客户端  
		lws_write(wsi, in, len, LWS_WRITE_TEXT);
		break;
		default:  
		 break;
	}
	return 0;
}
static struct lws_protocols protocols[] = { {
		"echo-protocol",  
		 callback_echo,  
		 0,  
		 128,
	}
	, {
		NULL, NULL, 0, 0
	}
	// 结束标记
}
;
int main(void) {
	struct lws_context_creation_info info;
	memset(&info, 0, sizeof info);
	info.port = 8000;
	// 服务端监听的端口号  
	info.protocols = protocols;
	// 使用自定义的协议  
	info.gid = -1;
	// 不使用组ID  
	info.uid = -1;
	// 不使用用户ID  
	info.options = LWS_SERVER_OPTION_HTTP_HEADERS;
	// 设置选项,允许HTTP头部字段存在消息中  
	struct lws_context *context = lws_create_context(&info);
	// 创建WebSocket服务器上下文  
	while (1) {
		// 循环运行服务器,直到手动停止  
		lws_service(context, 50);
		// 处理WebSocket连接,超时时间设置为50毫秒
	}
	lws_context_destroy(context);
	// 销毁WebSocket服务器上下文  
	return 0;
}

与libuv集成

关键点是libuv的异步I/O机制中调用libwebsockets提供的方法。示例程序如下:

#include <uv.h>  
#include <libwebsockets.h>  
  
static void on_read(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) {  
    struct lws *wsi = (struct lws *)stream->data;  
    int n;  
  
    if (nread < 0) {  
        lws_close(wsi, LWS_CLOSE_STATUS_GOINGAWAY, "UV read error");  
        return;  
    }  
  
    if (nread == 0)  
        return;  
  
    n = lws_write(wsi, buf->base, nread, LWS_WRITE_TEXT);  
    if (n < 0) {  
        lws_close(wsi, LWS_CLOSE_STATUS_GOINGAWAY, "Cannot write");  
        return;  
    }  
}  
  
static void on_write(uv_write_t *req, int status) {  
    struct lws *wsi = (struct lws *)req->data;  
    if (status) {  
        lws_close(wsi, LWS_CLOSE_STATUS_GOINGAWAY, "UV write error");  
        return;  
    }  
}  
  
static void service(struct lws *wsi) {  
    uv_loop(uv_default_loop()); // 开始事件循环  
}  
  
static int callback(struct lws *wsi, enum lws_callback_reasons reason) {  
    switch (reason) {  
        case LWS_CALLBACK_ESTABLISHED: // 当新的连接建立时触发  
            uv_write_t *req = (uv_write_t *)malloc(sizeof(*req)); // 创建UV写入请求对象  
            uv_buf_t buf = uv_buf_init((char *)"Hello, client!", 13); // 创建缓冲区对象,存储要写入的消息内容  
            uv_write(req, (uv_stream_t *)&wsi->stream, &buf, 1, NULL); // 向客户端写入消息,并关联回调函数on_write和请求对象req  
            req->data = wsi; // 将请求对象关联到WebSocket连接对象wsi上,方便后续处理请求时获取wsi对象  
            break;  
        case LWS_CALLBACK_RECEIVE: // 当接收到客户端发送的消息时触发  
            // 处理接收到的消息,这里只是简单地打印消息内容到控制台  
            printf("Received message: %s\n", (char *)in);  
            break;  
        default: // 其他情况处理,例如连接关闭等操作可以在这里处理  
            break;  
    }  
    return 0; // 返回0表示处理成功,否则表示处理失败,会触发回调函数on_close或on_error等操作  
}
作者:岬淢箫声
日期:2023年11月7日
版本:1.0
链接:http://caowei.blog.csdn.net

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/120987.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++】stack | queue | priority_queue | deque

一、stack栈 介绍 1.栈是一种特殊的线性表&#xff0c;其元素遵循“后进先出”的原则&#xff0c;即仅允许在在表的一端进行插入、删除操作&#xff0c;这一模式被称为“后进先出”或LIFO&#xff08;last in fisrt out&#xff09;。 2.从底层实现来看&#xff0c;stack是作…

adb and 软件架构笔记

Native Service&#xff0c;这是Android系统里的一种特色&#xff0c;就是通过C或是C代码写出来的&#xff0c;供Java进行远程调用的Remote Service&#xff0c;因为C/C代码生成的是Native代码&#xff08;机器代码&#xff09;&#xff0c;于是叫Native Service。 native服务…

真正解决jellyfin硬解码转码

前段时间入手一个DS423集成显卡UHD600&#xff0c;搭了一个jellyfin&#xff0c;发现网上关于硬解码的教程基本都存在问题&#xff0c;没有真正解决我的硬解码问题。经过一系列分析修改&#xff0c;最终实现硬解码。先贴效果图&#xff1a; 下载安装jellyfin这里就不叙述&#…

php加密解密的用法(对称加密,非对称加密)

加密和摘要的区别 ***摘要&#xff1a;是从已知的数据中&#xff0c;通过摘要计算出一个值&#xff0c;一个数据对应一个或多个摘要的值 *** 比如&#xff1a;md5 和 sha1 sha256 hash 就是得到一个特定的值 &#xff0c;同一个数据得到的md5 是一样的&#xff0c;不会改变的 比…

python自动化测试(十一):写入、读取、修改Excel表格的数据

目录 一、写入 1.1 安装 xlwt 1.2 增加sheet页 1.2.1 新建sheet页 1.2.2 sheet页写入数据 1.2.3 excel保存 1.2.4 完整代码 1.2.5 同一坐标&#xff0c;重复写入 二、读取 2.1 安装读取模块 2.2 读取sheet页 2.2.1 序号读取shee页 2.2.2 通过sheet页的名称读取she…

实用知识(工作中常用)

mybatis-plus联表查询 pom.xml坐标 <!-- mybatis-plus-join --> <dependency><groupId>com.github.yulichang</groupId><artifactId>mybatis-plus-join</artifactId><version>1.2.4</version> </dependency>使用步骤&…

【可视化Java GUI程序设计教程】第5章 Swing容器的使用

Swing采用自顶向下的方式构建GUI&#xff0c;即先创建容器&#xff0c;再向容器中添加组件。 “组件”面板中的Swing容器 5.1 面板容器&#xff08;JPanel&#xff09; 5.5.1 使用方法 创建面板有以下两种方法 &#xff08;1&#xff09;创建一个窗体&#xff08;JFrame&…

SAP BASIS SET_PARAMETER_ID_TOO_LONG

ji 原因 DATA:curvbelnid(40) TYPE c,"问题在这里curposnrid(40) TYPE c. "问题在这里curvbelnid sy-uname && VN.curposnrid sy-uname && PR.SET PARAMETER ID curvbelnid FIELD i_vbeln . SET PARAMETER ID curposnrid FIELD i_posnr . 改成 D…

ci-cd的流程

1、项目在gitlab上&#xff0c;从gitlab上使用git插件获取源码&#xff0c;构建成war包&#xff0c;所以使用tomcat作为运行环境 发布 &#xff1a;使用maven插件发布&#xff0c;使用ssh连接。

【Android】画面卡顿优化列表流畅度一

卡顿渲染耗时如图&#xff1a; 卡顿表现有如下几个方面&#xff1a; 网络图片渲染耗时大上下滑动反应慢&#xff0c;甚至画面不动新增一页数据加载渲染时耗时比较大&#xff0c;上下滑动几乎没有反应&#xff0c;画面停止没有交互响应 背景 实际上这套数据加载逻辑已经运行…

支持向量机 (SVM):初学者指南

照片由 Unsplash上的 vackground.com提供 一、说明 SVM&#xff08;支持向量机&#xff09;简单而优雅用于分类和回归的监督机器学习方法。该算法试图找到一个超平面&#xff0c;将数据分为不同的类&#xff0c;并具有尽可能最大的边距。本篇我们将介绍如果最大边距不存在的时候…

Failed to connect to github.com port 443:connection timed out

解决办法&#xff1a; 步骤1&#xff1a; 在这里插入图片描述 步骤2&#xff1a; -步骤3 &#xff1a;在git终端中执行如下命令&#xff1a; git config --global http.proxy http:ip:port git config --global https.proxy http:ip:port git config --global http.proxy htt…

重磅发布 OpenAI 推出用户自定义版 ChatGPT

文章目录 重磅发布 OpenAI 推出用户自定义版 ChatGPT个人简介 重磅发布 OpenAI 推出用户自定义版 ChatGPT OpenAI 首届开发者大会 (OpenAI DevDay) 于北京时间 11 月 7 日凌晨 02:00 开始&#xff0c;大会上宣布了一系列平台更新。其中一个重要更新是用户可以创建他们自己的自定…

智慧农业:农林牧数据可视化监控平台

数字农业是一种现代农业方式&#xff0c;它将信息作为农业生产的重要元素&#xff0c;并利用现代信息技术进行农业生产过程的实时可视化、数字化设计和信息化管理。能将信息技术与农业生产的各个环节有机融合&#xff0c;对于改造传统农业和改变农业生产方式具有重要意义。 图扑…

SysML理论知识

概述 由来 长期以来系统工程师使用的建模语言、工具和技术种类很多&#xff0c;如行为图、IDEF0、N2图等&#xff0c;这些建模方法使用的符号和语义不同&#xff0c;彼此之间不能互操作和重用。系统工程正是由于缺乏一种强壮的标准的建模语言&#xff0c;从而限制系统工程师和…

Makefile 介绍

目录 一、Makefile 的规则 二、一个示例 三、make 是如何工作的 四、makefile 中使用变量 五、让 make 自动推导 六、另类风格的 makefile 七、清空目标文件的规则 make 命令执行时&#xff0c;需要一个 Makefile 文件&#xff0c;以告诉 make 命令需要怎么样的去编译和…

用Python实现朴素贝叶斯垃圾邮箱分类

一、实验目的 通过本实验&#xff0c;旨在使用朴素贝叶斯算法实现垃圾邮箱分类&#xff0c;并能够理解并掌握以下内容&#xff1a; 了解朴素贝叶斯算法的基本原理和应用场景。 学习如何对文本数据进行预处理&#xff0c;包括去除标点符号、转换为小写字母、分词等操作。 理解特…

git 生成公钥

1、通过命令 ssh-keygen 生成 SSH Key&#xff1a; ssh-keygen -t ed25519 -C "Gitee SSH Key" 三次回车 2、查看生成的 SSH 公钥和私钥&#xff1a; ls ~/.ssh/ 3、把公钥设置到git id_ed25519.pub 4、测试 ssh -T gitgitee.com 成功&#xff01;&#xff01;&…

Hive3 on Spark3配置

1、软件环境 1.1 大数据组件环境 大数据组件版本Hive3.1.2Sparkspark-3.0.0-bin-hadoop3.2 1.2 操作系统环境 OS版本MacOSMonterey 12.1Linux - CentOS7.6 2、大数据组件搭建 2.1 Hive环境搭建 1&#xff09;Hive on Spark说明 Hive引擎包括&#xff1a;默认 mr、spark、…

从vue源码中看diff算法

一、v-for必须要指定key&#xff0c;其作用是什么&#xff1f; 在源码中有一个函数为&#xff0c;其中就是通过判断两个vnode的type和key进行判断&#xff0c;如果这两个属性相同&#xff0c;那么这两个vnode就是相同&#xff0c;所以在设置key的时候也不可以设置为object等无…