websocket 连接 C Server的尝试-Html5-优质IT资源分享社区

yutingzhinan
论坛版主
论坛版主
  • UID9
  • 粉丝1
  • 关注0
  • 发帖数36
阅读:458回复:0

websocket 连接 C Server的尝试

楼主#
更多 发布于:2016-06-17 23:28

websocket:
WebSocket 标准的方针是在浏览器中完结和服务器端双向通讯.双向通讯能够拓宽浏览器上的运用类型.
它是依据 TCP衔接的 全双工通讯,但与一般的TCP又不相同,它供给的是音讯流,而不是字节省。
依据 HTTP 长衔接的“服务器推”技能
这项技能是在Ajax今后 备受追捧的一项技能,
推送技能Server
Push的根底思维是将浏览器自动查询信息改为服务器自动发送信息。服务器发送一批数据,浏览器显现这些数据,同时确保与服务器的衔接。当服务器需求再次发送一批数据时,浏览器显现数据并坚持衔接。今后,服务器依然能够发送批量数据,浏览器持续显现数据,顺次类比。
客户端拉曳(Client Pull)
在客户端拖曳技能中,服务器发送一批数据,在HTTP呼应或文档头符号中刺进指令,让浏览器“在5秒内再次装入这些数据”或“10秒内前往某URL装入数据”。当指定的时刻达届时,客户端就依照服务器的指示去做,或许改写当时数据,或许调入新的数据。
在客户端,HTTP会坚持一个衔接到Server,
而一般的HTTP,则没有这个衔接,它经过
客户端自动像Server主张衔接恳求,自动获取数据,但这么就会有一个丧命的缺陷:“会发生许多无用的HTTP恳求。”
比方 Discuz论坛的短音讯:
它经过JS 设置一个时刻循环事情,必定时刻今后会激活事情向服务器主张一个HTTP恳求,取到数据经过js更改当时页面的数据。
如下图




假如在没有新数据的情况下,关于服务器来讲,这个HTTP恳求即是无意义的衔接,在并发量很大的站点中,会给服务器形成很大的压力。
所以…服务器推送 呈现了。
它有个别号 Comet !
在client会坚持一个HTTP衔接到server,这个衔接成功今后,server会不断的循环检查数据是不是存在,假如存在,那么就像客户端发送这些数据。
它的长处明白明了。
如今已经有许多不错的技能在出产环境中运用了:
1、 经过 Flash作为中心节点,客户端与server的恳求经过Flash来转发。
此办法的缺陷
客户端有必要安装 Flash 播放器;
由于 XMLSocket 没有 HTTP 地道功能,XMLSocket 类不能自动穿过防火墙;
由于是运用套接口,需求设置一个通讯端口,防火墙、代理服务器也可能对非 HTTP 通道端口进行约束;
2、Java Applet 套接口
在客户端运用 Java Applet,经过 java.net.Socket 或 java.net.DatagramSocket 或
java.net.MulticastSocket 树立与服务器端的套接口衔接,然后完结“服务器推”。
这种计划最大的缺乏在于 Java applet 在收到服务器端回来的信息后,无法经过 javascript 去更新 HTML 页面的内容。
3、依据Ajax的轮询
AJAX 的呈现使得 JavaScript 能够调用 XMLHttpRequest 目标宣布 HTTP 恳求,JavaScript
呼应处理函数依据服务器回来的信息对 HTML 页面的显现进行更新。运用 AJAX 完结“服务器推”与传统的 AJAX 运用不相同之处在于:
服务器端会堵塞恳求直到有数据传递或超时才回来。
客户端 JavaScript 呼应处理函数会在处理完服务器回来的信息后,再次宣布恳求,从头树立衔接。
当客户端处理接纳的数据、从头树立衔接时,服务器端可能有新的数据抵达;这些信息会被服务器端保留直到客户端从头树立衔接,客户端会一次把当时服务器端一切的信息取回。
4、依据 Iframe 及 htmlfile 的流(streaming)方法
iframe 是很早就存在的一种 HTML 符号, 经过在 HTML 页面里嵌入一个隐蔵帧,然后将这个隐蔵帧的 SRC
属性设为对一个长衔接的恳求,服务器端就能源源不断地往客户端输入数据。
了解了这些,就能够再来谈谈WebSocket了
浏览器支撑
Chrome Supported in version 4+
Firefox Supported in version 4+
Internet Explorer Supported in version 10+
Opera Supported in version 10+
Safari Supported in version 5+
WebSocket 概述
WebSocket 协议本质上是一个依据 TCP 的协议。为了树立一个 WebSocket 衔接,客户端浏览器首要要向服务器主张一个 HTTP
恳求,这个恳求和通常的 HTTP 恳求不相同,包含了一些附加头信息,其间附加头信息”Upgrade: WebSocket”表明这是一个恳求协议升级的 HTTP
恳求,服务器端解析这些附加的头信息然后发生应对信息回来给客户端,客户端和服务器端的 WebSocket
衔接就树立起来了,两边就能够经过这个衔接通道自在的传递信息,而且这个衔接会持续存在直到客户端或许服务器端的某一方自动的封闭衔接。




To establish a WebSocket connection, the client sends a WebSocket handshake
request, and the server sends a WebSocket handshake response。
树立一个websocket衔接,客户端发送握手恳求,服务器回来握手呼应,
客户端发送的数据如下:
GET /mychat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Version: 13
Origin: http://example.com
服务器回来的数据如下:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
The handshake resembles HTTP, but actually isn’t. It allows the server to
interpret part of the handshake request as HTTP, then switch to WebSocket.
Note that each line ends with an EOL (end of line) sequence, \\n or \\r\\n.
There must be a blank line at the end.
这个握手很像HTTP,可是实际上却不是,它答应服务器以HTTP的方法解释一部分handshake的恳求,然后切换为websocket
留意,每一行完毕都要以EOL 空白符完毕,\\n 或许\\r\\n。
这儿是十分主要的当地!网上材料很少,我即是在这儿遇到了疑问,开端树立衔接今后,永久都不回来句柄,我认为只需求客户端像server发送数据,而server不必回来承认数据,看到这儿我才知道我错了!
The client sends a Sec-WebSocket-Key which is base64 encoded. To form a
response, the magic string 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 is appended to
this (undecoded) key. The resulting string is then hashed with SHA-1, then
base64 encoded. Finally, the resulting reply occurs in the header
Sec-WebSocket-Accept.
客户端发送 base64加密的
Sec-WebSocket-Key,服务器接纳到这个key今后,将258EAFA5-E914-47DA-95CA-C5AB0DC85B11拼在key今后,生成HSmrc0sMlYUkAGmm5OPpG2HaGWk=258EAFA5-E914-47DA-95CA-C5AB0DC85B11,然后将得到的成果进行sha-1哈希,最终base64加密,作为Sec-WebSocket-Accept的值
发送给客户端。
假如accept这个值过错的话会抛出 Error during WebSocket handshake: Sec-WebSocket-Accept
mismatch
最终封闭衔接。。必定要留意哦。
这么,握手才算完结!衔接承认今后,客户端及服务器端就能够相互发数据了。留意哦,它是全双工的哦,意思即是不会堵塞。
如图




概念性的疑问都明白了,来看看WEBSOCKET为咱们供给了哪些API
1、结构函数 WebSocket(char *host);
创立一个websocket目标,承受一个参数以ws://靠头,就像主张一个HTTP恳求相同用http://最初
var ws=new WebSocket(“ws://10.32.21.27:9880”);
2、ws.onopen
衔接成功后触发
3、ws.onerror
衔接犯错触发
4、ws.onmessage
server端有数据回来时触发
5、ws.onclose
封闭衔接时触发
还有一个最主要的
6、ws.send
用来发送音讯到server
7、ws.close
封闭衔接




完好的client端的代码如下
Connect
Send
Close




server端代码如下
/*
*
=====================================================================================
*
* Filename: socket.c
*
* Description:
*
* Version: 1.0
* Created: 07/09/2012 07:00:25 PM
* Revision: none
* Compiler: gcc
*
* Author: 斯人,imsiren.com
* Organization:
*
*
=====================================================================================
*/
#include
#include
#include
#include
#include
#include
#include
#include
#define PORT 9880
#define MAXLENGTH 1024+1
void parsestr(char *request,char *data){
int needle;
strcat(request,"HTTP/1.1 101 WebSocket Protocol Handshake\\r\\n");
strcat(request,"Upgrade:WebSocket\\r\\n");
strcat(request,"Connection:Upgrade\\r\\n");
//这个值等于 base64_encode(sha1(key+258EAFA5-E914-47DA-95CA-C5AB0DC85B11))
由于我这儿没有适宜的base64算法和sha1算法,所以就不写了。
strcat(request,"Sec-WebSocket-Accept:ZmQ5OWUxMjgwMTViNTEyM2FmZTRlOGViODZkNTk3OTBjMWRiYjBiYg==\\r\\n");
}
int main(int argc,char ** argv){
int sockfd,len,maxfd,ret,retval,newfd;
int reuse=1;
fd_set rwfd;
struct sockaddr_in l_addr;
struct sockaddr_in c_addr;
struct timeval tv;
char buf[MAXLENGTH];
char request[MAXLENGTH];
sockfd=socket(AF_INET,SOCK_STREAM,0);
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(int));
if(sockfd<0)
perror("socket");
l_addr.sin_port=htons(PORT);
l_addr.sin_family=AF_INET;
l_addr.sin_addr.s_addr=INADDR_ANY;
if(bind(sockfd,(struct sockaddr*)&l_addr,sizeof(struct
sockaddr))<0)
perror("bind");
listen(sockfd,5);
len=sizeof(struct sockaddr);
tv.tv_sec=5;
tv.tv_usec=0;
bzero(request,MAXLENGTH);
while(1){
newfd=accept(sockfd,(struct sockaddr*)&c_addr,&len);
if(newfd==-1){
perror("accept");
exit(1);
}else{
printf("%s is comming\\n",inet_ntoa(c_addr.sin_addr));
}
while(1){
FD_ZERO(&rwfd);
FD_SET(0,&rwfd);
FD_SET(newfd,&rwfd);
maxfd=0;
if(newfd>maxfd)
maxfd=newfd;
retval=select(maxfd+1,&rwfd,NULL,NULL,&tv);
if(retval==-1){
perror("select");
break;
/* }else if(retval==0){
printf("no data\\n");
continue;
*/
}else{
if(FD_ISSET(0,&rwfd)){
bzero(buf,MAXLENGTH);
fgets(buf,MAXLENGTH,stdin);
parsestr(request,buf);
len=send(newfd,request,MAXLENGTH,0);
if(len>0)
printf("i sayed:%s\\n",buf);
}
if(FD_ISSET(newfd,&rwfd)){
len=recv(newfd,buf,MAXLENGTH,0) ;
if(len>0){
if(strncmp(buf,"quit",4)==0){
close(newfd);
}
}else{
printf("client says:%s\\n",buf);
}
}
}
}
}
return 0;
server用select 做 非堵塞处理。。
没什么特别的,仅仅一个简略的收发server,client客户端衔接今后,
需求在server输入字符承认衔接,握手才干完结哦。
敞开监听,客户端衔接后 如下图




咱们能够看到 发过来的头内容。
最主要的即是 Sec-WebSocket-Key: m1ZF/Zd5hOP7Jh5d8mnDoA==了。




这个是咱们发回给client的头信息。。
这么客户端的onopen就会被触发。。。
一次握手今后就完结了。。。
尽管websocket十分好用,可是现在来看
很难运用到出产环境中,由于websocket是html5今后才有的,对浏览器的要求较高,上面尽管提到了浏览器支撑的版别,可是都还不稳定,websocket现在只归于草案阶段,IE6/7/8乃至9都不支撑。
参考文献:
http://www.websocket.org/
http://en.wikipedia.org/wiki/WebSocket
http://www.ibm.com/developerworks/cn/web/1112_huangxa_websocket/







优质IT资源分享社区为你提供此文。
本站有大量优质html5 css js等web前端开发教程视频,资料等资源,包含html5 css js 前端开发框架等基础教程,高级进阶教程等等,教程视频资源涵盖传智播客,极客学院,达内,北大青鸟,猎豹网校等等IT职业培训机构的培训教学视频,价值巨大。欢迎点击下方链接查看。
优质IT资源分享社区(www.itziyuan.top)
一个免费,自由,开放,共享,平等,互助的优质IT资源分享网站。
专注免费分享各大IT培训机构最新培训教学视频,为你的IT学习助力!

!!!回帖受限制请看点击这里!!!
!!!资源失效请在此版块发帖说明!!!

[PS:按 CTRL+D收藏本站网址~]


微信小程序开发

——“优质IT资源分享社区”管理员专用签名~

本版相似帖子

游客