- 浏览: 262705 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
ab0809:
写的很好,谢谢
c++中的 extern "C" -
eieihihi:
说得太好了,我就喜欢这种很透彻的说法
c++中的 extern "C" -
infollllll:
package com;import java.io.*;im ...
websocket通讯协议(10版本)简介 -
rocksent:
websocket draft10握手成功了,可是传数据一直失 ...
websocket通讯协议(10版本)简介 -
guanbeilang:
通过你的代码,学会了怎么从客户端接收消息,并改造成了nodej ...
websocket通讯协议(10版本)简介
前言:
工作中用到了websocket 协议10版本的,英文的协议请看这里:
http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-10
这篇文章相当于工作的总结吧。
首先, 你需要简单了解一下为什么会诞生websocket通讯协议,web上的通讯一般都是基于HTTP(超文本传输协议)的通讯,故而没有建立长时间的网络连接的方法,一般的通讯都是这样子的:
请求
浏览器--------------------->服务器
<-----------------------
响应
这种连接都是客户端发起的,服务器回复数据后关闭连接。
就好像你用浏览器访问百度输入www.baidu.com后,浏览器发起请求,百度的服务器将该页面的html超文本传给你的浏览器后关闭连接。
这种连接时间很短的, 而且服务器无法主动传送数据。
举几个例子:
优酷, 土豆这些网站可以在网上播放电影,播放电影需要持续传送数据的,故只能内嵌flash播放器,用flash中的flash socket持续传送数据。
用html, js等编写一个及时聊天软件是很困难的,关键就在于不能建立持续的连接,服务器不能主动传送数据给客户端。只能隔一段时间客户端发起请求主动询问服务器有无数据?
websocket可以建立稳定的连接,能解决上述的问题。
先说下原理,稍后会把代码文件穿上来给大家下载。
websocket通讯过程:
1.客户端发起连接请求
websocket客户端首先发起一个连接请求,发送的数据格式如下:
GET /10.15.1.218:12345/chat?key=value\r\n
HTTP/1.1\r\n
Upgrade: websocket\r\n
Connection: Upgrade\r\n
Host: 10.15.1.218:12345\r\n
Sec-WebSocket-Origin: null\r\n
Sec-WebSocket-Key: 4tAjitqO9So2Wu8lkrsq3w==\r\n
Sec-WebSocket-Version: 8\r\n\r\n
这是类似于HTTP的头,注意每行数据结尾结束符是"\r\n", 最后的结束符是"\r\n\r\n"。
请求头第1行详解:
“GET /”后面是服务器的IP和端口(10.15.1.218:12345)必须有。'/'的后面是你自己字符串,(chat),随便你传什么,这部分是可选的。字符串 ‘?’后面是一些参数(key=value),是什么你自己定义, 这部分也是可选的。像下面这三种都是合法的:
GET /10.15.1.218:12345\r\n
或者
GET /10.15.1.218:12345/chat\r\n
或者
GET /10.15.1.218:12345/chat?key=value\r\n
第2, 3, 4, 5, 6行:
HTTP/1.1\r\n
Upgrade: websocket\r\n
Connection: Upgrade\r\n
Host: 10.15.1.218:12345\r\n
Sec-WebSocket-Origin: null\r\n
这些都基本是固定的格式与内容,Host: 后面是服务器(被连接者)的IP和Port。
第7行:
Sec-WebSocket-Key: 4tAjitqO9So2Wu8lkrsq3w==\r\n
Sec-WebSocket-Key后面的那一串东西,那一串长度为24的字符串是客户端随机生成的,我们暂时叫他cli_key,服务器必须用它经过一定的运算规则生成服务器端的key,暂时叫做ser_key,然后把ser_key发回去,客户端验证正确后,握手成功!
第8行:
Sec-WebSocket-Version: 8\r\n\r\n
之所以版本为8的原因,我不太清楚。10版本的通讯协议中客户端发出的都是8。
chrome 14浏览器中实现了websocket客户端,不用自己实现。可以去下载一个,当websocket客户端用。
2.制作服务端的密钥
我们的服务器将key1(长度24)截取出来
4tAjitqO9So2Wu8lkrsq3w==
用它和自定义的一个字符串(长度36):
258EAFA5-E914-47DA-95CA-C5AB0DC85B11
连接起来,像这样:
4tAjitqO9So2Wu8lkrsq3w==258EAFA5-E914-47DA-95CA-C5AB0DC85B11
然后把这一长串经过SHA-1算法加密,得到长度为20字节的二进制数据,
再将这些数据经过Base64编码,最终得到服务端的密钥,也就是ser_key:
bEVeGLZrb9fS3Rj8WzExJdCsedg=
3.服务端返回密钥
然后需要把密钥返回给客户端,完成握手,发送的数据格式如下:
HTTP/1.1 101 Switching Protocols\r\n
Upgrade: websocket\r\n
Connection: Upgrade\r\n
Sec-WebSocket-Accept: bEVeGLZrb9fS3Rj8WzExJdCsedg=\r\n\r\n
至此,算是握手成功了!
4.传输数据(简单的介绍数据长度小于126的数据传输,传输大于等于126字节的数据头部(head)可就不止2个字节了,去看英文文档中介绍头部的部分)
必须有掩码
客户端----------------------->服务器
<-----------------------
掩码(可选)
协议中规定客户端发向服务器的数据必须有掩码,比如需要发送一个字符串“Hello”,
“Hello“的ascii码:
H e l l o
十六进制 0x48 0x65 0x6c 0x6c 0x6f
十进制 72 101 108 108 111
但是实际发出的数据是这样的:
------------------head-----掩码0----1-------2-------3-----H----e-----l------l-------o--------------
0x81 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58
head头部我不在这里说了,需要很多文字才能说明,自己去英文协议中相关地方查看一下吧,head后是4字节的掩码,随机生成的,再后面是数据了,你可能发现数据变了,这些数据是 hello的ascii码和掩码做异或运算算出来的。
运算规则是这样的, 第零个字符'H'和第零个掩码异或, 第一个字符'e'和第一个掩码异或......
其实就是用c语言表示就是res = str[n]^mask[n%4]
服务器发出数据可以有掩码, 也可以没有掩码
发出一个“Hello”字符串可以发出和客户端一样的数据,也可以发出像下面的无掩码的:
0x81 0x05 0x48 0x65 0x6c 0x6c 0x6f
H e l l o
这就是头部信息加上原始数据啦。
5. 关闭连接
这部分很简单,或许你可以去英文协议中找到它看一看。
- websocket_client.rar (1.2 KB)
- 下载次数: 402
- WebSocketServer.rar (5.8 KB)
- 下载次数: 462
评论
import java.io.*;
import java.net.*;
import java.security.MessageDigest;
import sun.misc.BASE64Encoder;
class ServeOneJabber extends Thread {
private Socket socket;
private BufferedReader in;
private PrintWriter out;
String ikey;
public ServeOneJabber(Socket s)
throws IOException {
socket = s;
in =
new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
// Enable auto-flush:
start(); // Calls run()
}
void send(){
try {
out =
new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(
socket.getOutputStream())), true);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
out.print("HTTP/1.1 101 Switching Protocols\r\n"+
"Upgrade: websocket\r\n"
+"Connection: Upgrade\r\n"
+"Sec-WebSocket-Accept: "+getSecWebSocketAccept(ikey)+"\r\n\r\n");
out.flush();
out.close();
}
public String getSecWebSocketAccept(String onekey) {
String guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
String key = "";
key = onekey;
key += guid;
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(key.getBytes("iso-8859-1"), 0, key.length());
byte[] sha1Hash = md.digest();
key = base64Encode(sha1Hash);
} catch (Exception e) {
}
System.out.println(onekey+":"+key);
return key;
}
public static String base64Encode(byte[] input) {
BASE64Encoder encoder = new BASE64Encoder();
String base64 = encoder.encode(input);
return base64;
}
public void run() {
System.out.println("开始传输==>");
try {
while (true) {
String str = in.readLine();
if (str.equals("")) break;
if(str.indexOf("Sec-WebSocket-Key: ")>-1)
ikey=str.substring(19);
System.out.println(str);
}
System.out.println("<==传输完毕");
send();
} catch (IOException e) {
}
}
}
public class SKT {
static final int PORT = 1201;
public static void main(String[] args)
throws IOException {
ServerSocket s = new ServerSocket(PORT);
System.out.println("Server Started");
try {
while(true) {
// Blocks until a connection occurs:
Socket socket = s.accept();
try {
new ServeOneJabber(socket);
} catch(IOException e) {
// If it fails, close the socket,
// otherwise the thread will close it:
socket.close();
}
}
} finally {
s.close();
}
}
} ///:~
加出来的0x81 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58是怎么组成格式被send调用的,英文太差,协议看不懂啊
实在是感激不尽啊~~~
发表评论
-
c++ vector list map在遍历中删除元素
2013-05-07 14:47 5068c++ STL 中的vector, list, map ... -
c++ 构造函数和析构函数调用顺序
2013-04-25 16:54 1211#include <iostream> ... -
epoll高效的原因
2013-03-18 11:10 1058epoll高效的原因: 使用内核中断实现,中断后调用 ... -
UNIX domain socket传递文件描述符
2012-06-19 18:41 5454c版本(UNIX高级编程中的例子): // sendm ... -
unix domain socket传递描述符
2012-04-25 15:18 980用unix domain socket在进程间传递描述符。 ... -
C++中的虚函数和虚函数表
2012-04-02 18:17 973请看这一篇文章: http://hi.baidu.com/w ... -
c++中函数参数返回值用string好还是const char *好
2012-02-01 07:38 9833有这样一个函数test需要两个字符串作为参数,那么test的原 ... -
google的gtest测试框架
2011-12-21 18:17 870http://www.cnblogs.com/coderzh/ ... -
windows下TCP通讯
2011-12-20 18:17 1071客户端 #include <iostream> ... -
静态库与共享库
2011-11-01 19:00 1718在用c c++编程时经常用到库,库有静态的,和共享 ... -
c++线程池
2011-09-26 09:17 841 -
epoll服务器
2011-09-21 22:33 815epoll服务器。 ... -
c,c++ little knowledge
2011-08-31 15:00 6811. 把一个string型字符串全部转成小写。 ... -
c++中的拷贝构造函数
2011-07-14 16:44 1137int a = 2; int b = a; ... -
简单的tcp通讯
2011-07-12 14:55 896简单的tcp通讯例子。 server端 /* ... -
c++中的 extern "C"
2011-06-21 20:33 23818比如说你用C 开发 ... -
c语言操作mysql数据库(Ubuntu11.04)
2011-06-11 17:43 2940系统:Ubuntu11.04 1.刚安装 ... -
全局宏定义
2010-12-22 22:59 5494首先我们要理解定义和声明的区别,举个常见的例子,比 ...
相关推荐
WebSocket通讯测试工具是一种用于调试和测试WebSocket网络协议的应用程序,主要针对HTML版本的Web应用程序。WebSocket协议是HTTP协议的一个扩展,旨在提供双向通信能力,使得服务器和客户端可以实时、高效地交换数据...
在本案例中,我们将探讨如何使用Vue.js和Delphi 10.2之间的WebSocket通讯来读取卡信息。 1. **Vue.js中的WebSocket集成**: Vue.js本身并不直接支持WebSocket,但可以通过第三方库如`vue-websocket`或手动创建...
在易语言中实现WebSocket通讯,可以极大地提升网络应用的交互性,特别是对于需要实时更新数据的场景,如在线游戏、股票行情、聊天室等。 易语言是一门以中文编程为特色的编程语言,它以简洁直观的语法设计,使得...
这个"Android-WebSocket通讯例子"的DEMO应该包含了上述基本步骤的实现,对于初学者来说,这是一个很好的起点。通过分析和运行DEMO,你可以更深入地理解WebSocket在Android中的工作原理和应用方法。同时,别忘了测试...
总的来说,"C#_WinForm实现WebSocket及时通讯"项目涉及到C#编程、WinForm界面设计、WebSocket协议的使用以及SuperWebSocket库的集成。通过这个项目,开发者可以学习如何在Windows桌面应用中实现双向、实时的数据传输...
在给定的"WebSocket通讯实例,包含Winform通讯实例"中,我们可以推测这是一个教学或示例项目,涵盖了WebSocket在Web页面和Windows窗体应用中的实现。这个实例包括了以下几个关键知识点: 1. WebSocket协议基础:...
学习和理解这个WebSocket通讯范例,可以帮助开发者掌握WebSocket的基本用法,从而在实时聊天应用、在线游戏、股票交易系统等需要实时数据交互的场景中应用WebSocket技术。通过分析和调试示例代码,你可以深入理解...
标题和描述中提到的《WebSocket协议中文版》是RFC6455文档的中文翻译版本,该文档详细描述了WebSocket协议的技术细节。WebSocket协议是一种支持客户端和服务器之间进行全双工通信的协议,它允许在web浏览器和服务器...
RFC6455是WebSocket协议的官方文档标准版本,由互联网工程任务组(IETF)制定,是互联网标准跟踪文件。 ### WebSocket协议概述 WebSocket协议的主要目的是为了解决传统HTTP协议在需要服务器和客户端双向通信时效率...
WebSocket是一种在客户端和服务器之间建立持久连接的协议,它提供了双向通信的能力,使得数据可以在两者之间实时、高效地传输。在本项目中,我们将探讨如何使用C#实现WebSocket服务器,并结合JavaScript实现...
在"WebSocket 通讯源码2.1"中,我们有两个关键部分:客户端和服务器端。客户端源码实现了向服务器发送文字、图片、附件和表情的功能,这涵盖了多种数据类型的传输。而服务端工具则负责接收和处理来自客户端的这些...
WebSocket是一种在客户端和服务器之间建立长久连接的协议,它允许双向通信,即服务器和客户端都可以主动发送数据。在Qt中,我们可以利用Qt网络模块中的QWebSocket类来实现WebSocket通信。 首先,让我们了解一下Qt库...
WebSocket是一种在客户端和服务器之间建立长连接的协议,它提供了双向通信的能力,即服务器和客户端都可以主动发送数据。...开发者可以通过研究这个示例,了解如何在实际项目中实现WebSocket通讯。
Unity Best HTTP2 2.6.2 插件 帮助开发者快速构建WebSocket,Http通讯模块 亲测可用 放心下载
在本项目中,“C# 服务端与WebSocket通讯.rar”提供了使用C#语言开发的服务端代码,实现了与网页WebSocket进行数据通信的功能,以创建一个类似在线聊天室的应用。 首先,我们需要了解C#中的WebSocket通信基础。...
WebSocket通讯框架jWebSocket是用于构建实时、双向通信应用的一个强大工具。它基于WebSocket协议,这是一种在Web上实现低延迟、高效率数据传输的网络协议。WebSocket使得客户端和服务器之间的数据交换变得更加简单,...
WebSocket是一种在客户端和服务器之间建立持久连接的协议,它允许双方进行实时、双向的数据交换,非常适合需要低延迟、高效率通信的应用场景,如在线游戏、实时聊天和股票交易等。在iOS开发中,与HTML5(H5)的...