精华内容
下载资源
问答
  • 1)ws客户端其实是能直接连接tcp服务器的 但是可见连接后,直接error-->close了,这是因为没有握手协议的支持,所以失败, 2)下面添加了握手协议后,tcp服务器就可以升级为ws服务器 3)client.html <!...

    1)ws客户端其实是能直接连接tcp服务器的

    但是可见连接后,直接error-->close了,这是因为没有握手协议的支持,所以失败,

    2)下面添加了握手协议后,tcp服务器就可以升级为ws服务器

    3)client.html

    <!DOCTYPE html>
    <html>
    <head>
      <title>skynet WebSocket example</title>
    </head>
    <body>   
      <script>
        var ws = new WebSocket('ws://127.0.0.1:8001/ws');
    
        ws.onopen = function(){
         alert("open");
         ws.send('WebSocket'); 
        };
        ws.onmessage = function(ev){
         alert(ev.data);
        };
        ws.onclose = function(ev){
         alert("close");
        };
        ws.onerror = function(ev){
            console.log(ev);
         alert("error");
        };
    
      </script>
    </body>
    </html>

    4)server.c

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    #include "uv.h"
    
    #include "../3rd/http_parser/http_parser.h"
    #include "../3rd/crypto/sha1.h"
    #include "../3rd/crypto/base64_decoder.h"
    #include "../3rd/crypto/base64_encoder.h"
    
    struct ws_context{
    	int is_shake_hand;
    	char* data; // 读取数据的buff
    };
    
    static uv_loop_t* loop = NULL;
    static uv_tcp_t l_server;
    
    static void 
    uv_alloc_buf(uv_handle_t* handle, size_t suggested_size,uv_buf_t* buf) {
    
    	struct ws_context* wc = handle->data;
    
    	if (wc->data != NULL) {
    		free(wc->data);
    		wc->data = NULL;
    	}
    
    	buf->base = malloc(suggested_size + 1);
    	buf->len = suggested_size;
    	wc->data = buf->base;
    }
    
    static void
    on_close(uv_handle_t* handle) {
    	printf("client close!\n");
    	if (handle->data) {
    		struct ws_context* wc = handle->data;
    		free(wc->data);
    		wc->data = NULL;
    		free(wc);
    
    		handle->data = NULL;
    	}
    
    	free(handle);
    }
    
    static void
    on_shutdown(uv_shutdown_t* req, int status) {
    	uv_close((uv_handle_t*)req->handle, on_close);
    	free(req);
    }
    
    static void
    after_write(uv_write_t* req, int status) {
    	if (status == 0) {
    		printf("write success!\n");
    	}
    
    	uv_buf_t* w_buf = req->data;
    	if (w_buf) {
    		free(w_buf);
    	}
    	free(req);
    }
    
    static void
    send_data(uv_stream_t* stream, unsigned char* send_data, int send_len) {
    
    	uv_write_t* w_req = malloc(sizeof(uv_write_t));
    	uv_buf_t* w_buf = malloc(sizeof(uv_buf_t));
    
    	unsigned char* send_buf = malloc(send_len);
    	memcpy(send_buf, send_data, send_len);
    
    	w_buf->base = send_buf;
    	w_buf->len = send_len;
    	w_req->data = w_buf;
    
    	uv_write(w_req, stream, w_buf, 1, after_write);
    }
    
    static char field_sec_key[512];
    static char value_sec_key[512];
    static int is_sec_key = 0;
    static int has_sec_key = 0;
    
    static int 
    on_ws_header_field(http_parser* p, const char* at, size_t length) {
    	if (strncmp(at, "Sec-WebSocket-Key", length) == 0) {
    		is_sec_key = 1;
    	}
    	else
    	{
    		is_sec_key = 0;
    	}
    
    	return 0;
    }
    
    static int
    on_ws_header_value(http_parser* p, const char* at, size_t length) {
    	if (!is_sec_key) {
    		return 0;
    	}
    
    	strncpy(value_sec_key, at, length);
    	value_sec_key[length] = 0;
    	has_sec_key = 1;
    	return 0;
    }
    
    static char* wb_magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
    
    static char* wb_accept = 
    "HTTP/1.1 101 Switching Protocols\r\n"
    "Upgrade:websocket\r\n"
    "Connection: Upgrade\r\n"
    "Sec-WebSocket-Accept: %s\r\n"
    "Websocket-Protocol:chat\r\n\r\n";
    
    static void
    ws_connect_shake_hand(uv_stream_t* stream, unsigned char* data, int data_len) {
    	http_parser_settings settings;
    	http_parser_settings_init(&settings);
    
    	settings.on_header_field = on_ws_header_field;
    	settings.on_header_value = on_ws_header_value;
    
    	http_parser p;
    	http_parser_init(&p, HTTP_REQUEST);
    	is_sec_key = 0;
    	has_sec_key = 0;
    	http_parser_execute(&p, &settings, data, data_len);
    
    	if (has_sec_key) { // 解析握手成功
    		printf("Sec-Websocket-Key: %s\n", value_sec_key);
    
    		static char key_magic[512]; // key+migic
    		static char sha1_key_migic[SHA1_DIGEST_SIZE]; // 经过sha1加密后的 key+migic
    		static char send_client[512]; // 发给客户端的握手数据
    
    		int sha1_size;
    
    		sprintf(key_magic, "%s%s", value_sec_key, wb_magic);
    
    		// sha1的结果:sha1_key_migic  sha1后的长度:sha1_size
    		crypt_sha1((unsigned char*)key_magic, strlen(key_magic), (unsigned char*)&sha1_key_migic, &sha1_size); 
    
    		int base64_len;
    		char* base_buf = base64_encode(sha1_key_migic, sha1_size, &base64_len); // 得到base64结果
    
    		sprintf(send_client, wb_accept, base_buf); // 得到最终握手数据
    		base64_encode_free(base_buf);
    
    		send_data(stream, (unsigned char*)send_client, strlen(send_client));
    	}
    }
    
    static void
    ws_send_data(uv_stream_t* stream, unsigned char* data, unsigned int len) {
    	int head_size = 2;
    	if (len > 125 && len < 65536) {
    		head_size += 2;
    	}
    	else if (len >= 65536) {
    		head_size += 8;
    	}
    
    	unsigned char* data_buf = malloc(head_size + len);
    	data_buf[0] = 0x81;
    	if (len <= 125) {
    		data_buf[1] = len;
    	}
    	else if (len > 125 && len < 65536) {
    		data_buf[1] = 126;
    		data_buf[2] = (len & 0x0000ff00) >> 8;
    		data_buf[3] = (len & 0x000000ff);
    	}
    	else
    	{
    		return;
    	}
    
    	memcpy(data_buf + head_size, data, len);
    	send_data(stream, data_buf, head_size + len);
    	free(data_buf);
    }
    
    static void 
    ws_on_recv_data(uv_stream_t* stream, unsigned char* data, unsigned int len) {
    	if (data[0] != 0x81 && data[0] != 0x82) {
    		return;
    	}
    
    	unsigned int data_len = data[1] & 0x0000007f;
    	int head_size = 2;
    	if (data_len == 126) {
    		data_len = data[3] | (data[2] << 8);
    		head_size += 2;
    	}
    	else if (data_len == 127) {
    		unsigned int low = data[5] | (data[4] << 8) | (data[3] << 16) | (data[2] << 24);
    		unsigned int height = data[9] | (data[8] << 8) | (data[7] << 16) | (data[6] << 24);
    		data_len = low;
    		head_size += 8;
    	}
    
    	unsigned char* mask = data + head_size;
    	unsigned char* body = data + head_size + 4;
    
    	for (unsigned int i = 0; i < data_len; i++) {
    		body[i] = body[i] ^ mask[i % 4];
    	}
    
    	//test
    	static char test_buf[4096];
    	memcpy(test_buf, body, data_len);
    	test_buf[data_len] = 0;
    	printf("%s\n", test_buf);
    
    	ws_send_data(stream, "Hello", strlen("Hello"));
    }
    
    static void 
    after_read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
    	if (nread < 0) {
    		uv_shutdown_t* reg = malloc(sizeof(uv_shutdown_t));
    		memset(reg, 0, sizeof(uv_shutdown_t));
    		uv_shutdown(reg, stream, on_shutdown);
    		return;
    	}
    
    	printf("start websocket!!!\n");
    
    	struct ws_context* wc = stream->data;
    	if (wc->is_shake_hand == 0) {
    		ws_connect_shake_hand(stream, buf->base, buf->len);
    		wc->is_shake_hand = 1;
    		return;
    	}
    
    	// 客户端主动关闭
    	if ((unsigned char)(buf->base[0]) == 0x88) {
    		printf("ws closing!!!\n");
    		return;
    	}
    
    	// 正常的数据
    	ws_on_recv_data(stream, buf->base, nread);
    }
    
    static void
    uv_connection(uv_stream_t* server, int status) {
    	printf("new client come in\n");
    	uv_tcp_t* client = malloc(sizeof(uv_tcp_t));
    	memset(client, 0, sizeof(uv_tcp_t));
    	uv_tcp_init(loop, client);
    	uv_accept(server, (uv_stream_t*)client);
    
    	//让event loop管理读
    	struct ws_context* wc = malloc(sizeof(struct ws_context));
    	memset(wc, 0, sizeof(struct ws_context));
    	client->data = wc;
    
    	uv_read_start((uv_stream_t*)client, uv_alloc_buf, after_read);
    }
    
    int main(int argc, char** argv) {
    	int ret;
    
    	loop = uv_default_loop();
    
    	uv_tcp_init(loop, &l_server);
    
    	// 配置我想要eventloop帮我管理的类型
    	struct sockaddr_in addr;
    	uv_ip4_addr("0.0.0.0", 8001, &addr);
    	ret = uv_tcp_bind(&l_server, (const struct sockaddr*)&addr, 0);
    	if (ret != 0) {
    		goto failed;
    	}
    	uv_listen((uv_stream_t*)&l_server, SOMAXCONN, uv_connection);
    
    	uv_run(loop, UV_RUN_DEFAULT);
    
    failed:
    	printf("end\n");
    	system("pause");
    	return 0;
    }

    5)数据收发协议测试

    服务器收到和客户端发来的WebSocket字符串,客户端也受到服务器发来的Hello字符串

    握手过程:

    1.客户端发送 一段 http报文

    2.服务器收到报文,通过http_parser解析到 Sec-WebSocket-Accept 对应的 客户端握手value

    3.migic是固定的 static char* wb_migic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

    4.把客户端解析到的          base64(sha1( 客户端握手value +magic )), 也就是先sha1算法,在base64编码后,得到握手内容,发送给ws客户端,就完成了握手! 此时,ws客户端就可以连接上升级后的tcp服务器了。

    总结:

    ws协议等价于 = 实现了 握手、发送数据、接受数据、关闭数据 这4个协议的tcp协议

    展开全文
  • WebSocket与http协议一样都是基于TCP的,所以他们都是可靠的协议,Web开发者调用的WebSocket的send函数在browser 的实现中最终都是通过TCP的系统接口进行传输的。WebSocket和Http协议一样都属于应用层的协议,那么...

    WebSocket与http协议一样都是基于TCP的,所以他们都是可靠的协议,Web开发者调用的WebSocket的send函数在browser 的实现中最终都是通过TCP的系统接口进行传输的。WebSocket和Http协议一样都属于应用层的协议,那么他们之间有没有什么关系呢?答案是肯定 的,WebSocket在建立握手连接时,数据是通过http协议传输的,正如我们上一节所看到的“GET/chat HTTP/1.1”,这里面用到的只是http协议一些简单的字段。但是在建立连接之后,真正的数据传输阶段是不需要http协议参与的。

    Note:
    WebSocket 是基于 HTTP 1.1 的一个功能,它本身是依赖 HTTP 的(使用 101 状态码来切换协议)。
    在OSI模型中,TCP是第四层传输层的协议,HTTP是第七层应用层的协议。

    具体关系可以参考下图:

    528967-20171012113904121-1073670739.png




    参考

    转载于:https://www.cnblogs.com/hongjh/p/7655381.html

    展开全文
  • WebsocketTCP的区别

    千次阅读 2021-05-22 10:05:38
    在这三者之间,SPDY和WebSocket都是与HTTP相关的协议,而TCP是HTTP底层的协议。 WebSocket则提供使用一个TCP连接进行双向通讯的机制,包括网络协议和API,以取代网页和服务器采用HTTP轮询进行双向通讯的机制。 ...

    按照OSI网络分层模型,IP是网络层协议,TCP是传输层协议,而HTTP是应用层的协议。在这三者之间,SPDY和WebSocket都是与HTTP相关的协议,而TCP是HTTP底层的协议。

    WebSocket则提供使用一个TCP连接进行双向通讯的机制,包括网络协议和API,以取代网页和服务器采用HTTP轮询进行双向通讯的机制。

    本质上来说,WebSocket是不限于HTTP协议的,但是由于现存大量的HTTP基础设施,代理,过滤,身份认证等等,WebSocket借用HTTP和HTTPS的端口。

    由于使用HTTP的端口,因此TCP连接建立后的握手消息是基于HTTP的,由服务器判断这是一个HTTP协议,还是WebSocket协议。 WebSocket连接除了建立和关闭时的握手,数据传输和HTTP没丁点关系了。

    WebSocket也有自己一套帧协议。

    展开全文
  • 最近学习到了websocket,Beego等知识。 因此看了Beego官方的一个聊天室...1.tcp属于传输层协议,websocket属于应用层协议(http也属于应用层) 2.两者都可以一次握手连续通话,http是一次请求一次回复即完成一次通

    最近学习到了websocket,Beego等知识。

    因此看了Beego官方的一个聊天室例子——利用websocket实现的网页版实时会话程序。

    此时想起之前一个利用tcp完成的黑窗口聊天室项目。

    两者之间貌似相同,都是客户端与服务器之间建立连接一直相互通话,直到连接断开结束通话。(其实这个相同点是搞明白他们的异同之后才想到的)。

    两者异同点:

    1.tcp属于传输层协议,websocket属于应用层协议(http也属于应用层)

    2.两者都可以一次握手连续通话,http是一次请求一次回复即完成一次通话。

    3.websocket是为了解决网页实时通话问题而产生的HTML5中新增的协议。

    4.websocket和http都是基于tcp协议实现的,websocket利用http协议完成握手并将http升级成websocket协议从而完成握手、实时通信功能。

    5.tcp协议是传输层协议,属于流模式面向连接,传输大量数据,比较可靠安全。

    到此已经基本可以看出websocket底层其实就是tcp,他们两个都可以通过多协程处理多连接实时传输完成群聊功能。

    2021-8-1修改:

    今天又拿go的net包去敲了一下黑窗口聊天室,构思的时候发现看似简单拿来直接用的东西,其实底层还是有好多东西没有理解透彻(灯下黑)。

    1.web编程各种框架、包已经封装好了底层内容,会自动起多个协程分别处理每个请求和通话。

    而net包相对来说比较靠近底层。好多东西需要我们自己去实现,就多个请求通话来说,需要我们去监听并循环接入,手动起多个协程去处理。而在封装好的各种web框架中已经帮我们处理好了,从而导致我编写黑窗口聊天室又忽略了这一点。

    展开全文
  • tcp如何实现websocket协议websocket使用场景流程如何验证合法性 websocket 使用场景 当server主动给client发送数据时。 思考:reactor+websocket如何封装? 流程 server发给client数据的前提是:确保client与server...
  • 基于Tcp socket通信的Pyqt5仿QQ,增加支持数据库,qq,登录,注册,群聊功能
  • 1. http协议:是用在应用层的协议,基于tcp协议,http协议建立链接也必须要有三次握手才能发送信息。 只能从客户端申请相应的请求到服务端,再从服务端获取返回数据。2.WebSocket:应用层协议,高效的解决Http协议...
  • 网页通常不能直接与tcp连接的设备直接通讯,虽然都是基于tcp,但是协议解析有点差别,通常是在服务器弄一个websocket代理,把tcp协议的数据转成websocket协议规范的数据,然后转发到真正的websocket服务器。...
  • 与此同时随着互联网的发展在HTML5中提出了websocket协议,能更好的节省服务器资源和带宽并且服务器和浏览器能够双向实时通讯。为了能让用户体验传统客户端和web带来的即时通信结合的超爽体验,本次毕业设计将完成web...
  • 全面理解WebSocket与Socket、TCP、HTTP的关系及区别 转:http://www.webzsky.com/?p=1388 1.什么是WebSocket及原理 WebSocket是HTML5中新协议、新API。 WebSocket从满足基于Web的日益增长的实时通信需求应运而生,...
  • Websocket,HTTP,TCP

    2019-12-07 20:30:45
    WebsocketTCP的关系 WebSocket与HTTP 同:建立在TCP之上,同http一样通过TCP来传输数据 不同:HTTP协议为单向协议,即浏览器只能向服务器请求资源,服务器才能将数据传送给浏览器,而服务器不能主动向浏览器...
  • 看了之后思维还是很混乱,甚是说websocket基于tcp的。现在想想误导了我好久。既然来问区别的了对吧,基础谁不知道呢。直接上关键:websocket与tcp的联系:websocket建立握手是通过http的,后面真正传输不再进行...
  • 传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793 [1] 定义。   什么是udp? 用户数据报协议(UDP,User Datagram Protocol)。...
  • WebSocket与http协议一样都是基于TCP的,所以他们都是可靠的协议,Web开发者调用的WebSocket的send函数在browser的实现中最终都是通过TCP的系统接口进行传输的。WebSocket和Http协议一样都属于应用层的协议,那么...
  • 1、代理服务基于go语言实现 2、代理服务源码 package main import ( "flag" "fmt" "log" "net" "net/http" "os" "runtime" "github.com/gorilla/websocket" ) var g_tcpAddress string var ...
  • HTTP、TCP/IP、Socket与WebSocket的区别!

    千次阅读 2017-11-08 23:25:00
    Socket是通信的雨花石,支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,内含了网络通信须有的五中信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远程主机的IP地址,...
  • 利用C++ SOCKET编程,自我实现的一个websocket服务器,能够比较好的移植,没有使用开源库
  • 详情见: ...sub=B79B7EF52C9D420F83D28E201B48FCD7 ...关于TCP/IP协议所处的位置,上层模型基于下层模型,也就是我们在使用HTTP协议时时基于TCP/IP实现的。 三次握手(建立连接),四次挥手(断开连接) ssl...
  • 转自:http://blog.csdn.net/sinat_31057219/article/details/72872359https://www.jianshu.com/p/42260a2575f8TCP/IP协议栈主要分为...(高速公路)TCP和UDP:传输层协议;(卡车)HTTP:应用层协议;(货物)。HT...
  • webSocket1.websocket背景简介2.websocket的客户端使用方式3.websocket服务端使用方式1.websocket背景介绍HTTP和WebSocket两者的差距不大浏览网页时,经过三个过程1、浏览器经过三次握手与web服务器建立链接,2、web...
  • 马夫 模板待办事项列表 创建一个新的项目。 验证 ,和。 查看。 首次。 在上述自述标记中设置插件ID。... 单击顶部的“监视”按钮,以通知有关包含新功能和修复的版本。... 这个花哨的IntelliJ平台插件将成为... 基于
  • websocket是一个基于应用层的网络协议,建立在tcp协议之上,和http协议可以说是兄弟的关系,但是这个兄弟有点依赖http,为什么这么说?我们都知道http实现了三次握手来建立通信连接,实际上websocket的创始人很聪明...
  • WebSocket与http协议一样都是基于TCP的,所以他们都是可靠的协议,Web开发者调用的WebSocket的send函数在browser的实现中最终都是通过TCP的系统接口进行传输的。WebSocket和Http协议一样都属于应用层的协议,那么...
  • ICP/IP协议(Transmission Control Protocol/InternetProtocol):网络通讯协议,是Internet最基本的协议、Internet国际互联网络的基础,由网络层的IP协议和传输层的TCP协议组成。协议采用了4层的层级结构,每一层都...
  •  WebSocket从满足基于Web的日益增长的实时通信需求应运而生,解决了客户端发起多个Http请求到服务器资源浏览器必须要在经过长时间的轮询问题,实现里多路复用,是全双工、双向、单套接字连接,在WebSocket协议下...
  • JSTP / JavaScript传输协议 JSTP是一个RPC协议和框架,提供双向异步数据传输,并支持多个并行非阻塞交互,该交互非常透明,以至于应用程序甚至无法区分本地异步功能和远程过程。 而且,作为一项不错的奖励,捆绑了...
  • 写在前面,公司最近在有关于通过手机或者硬件上报...单独把Scoket列出来是因为,他不是一个协议,他是两个应用程序之间互相通信得管道,在TCP/IP得上一层,也就是在传输层和应用层之间的抽象层,是一组API,他可以创建T...
  • 文章目录网络五层协议HTTP协议什么是HTTP协议HTTP 连接HTTP和TCP/IP的关系WebSocket协议WebSocket的由来比起HTTP,WebSocket好在哪里WebSocket和HTTP的关系Socket什么是SocketSocket和TCP/IP的关系WebSocket 与 ...
  • 通常,我们使用Nginx为后端WEB服务做反向代理或负载均衡,但如果我们的后端服务,并不是HTTP/HTTPS协议,而是TCP协议或WebSocket协议呢 最近遇到一个需求,我们的HTTPS以及MQTT服务端在海外云主机上,从大陆直连延时...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 21,002
精华内容 8,400
关键字:

websocket基于tcp