博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【WebSocket No.1】实现服务端webSocket连接通讯
阅读量:6832 次
发布时间:2019-06-26

本文共 6075 字,大约阅读时间需要 20 分钟。

前言

现阶段socket通信使用TCP、UDP协议,其中TCP协议相对来说比较安全稳定!本文也是来讲解TCP为主(恕在下学艺不精)。      

下面是个人理解的tcp/ip进行通讯之间的三次握手!

1.客户端先发送报文到服务端

2.服务端接受到报文之后进行回复

3.客户端收到回复之后再次发送确认信息。这个时候才是正式进行连接。

什么是WebSocket 

WebSocket 是一种网络通信协议。RFC6455 定义了它的通信标准。

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

与传统的HTTP协议对比:

HTTP 协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求做出应答处理。也就是说HTTP没有办法做到在客户端不请求服务器的情况下主动给客户端发送消息。但是这种情况有时确实我们必须的。当然我们在WebSocket之前我们也是有办法解决的,比如我们使用轮询技术来实现一部分的目的,但是有了WebSocket是必轮询更加合理的解决方案。

WebSocket API介绍

创建WebSocket 对象,这是所有步骤的第一步。

var Socket = new WebSocket(url, [protocol] );

WebSocket 对象属性

Socket.readyState:只读属性 readyState 表示连接状态,可以是以下值:0 - 表示连接尚未建立。1 - 表示连接已建立,可以进行通信。2 - 表示连接正在进行关闭。3 - 表示连接已经关闭或者连接不能打开。

Socket.bufferedAmount:只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。

WebSocket 事件

WebSocket 存在基本的的四个事件处理

Socket.onopen:连接建立时触发

Socket.onmessage:客户端接受到服务器发送的消息时候触发

Socket.onerror:通许期间发生错误时触发

Socket.onclose:连接关闭触发,不管你主动还是被动的

WebSocket 方法

Socket.send():发送消息给服务器

Socket.close():关闭连接,客户端主动关闭。

连接形式:

      服务器监听:服务器开启服务之后,就进入了监听客户端连接状态。此时不是指定监听那台客户端那是处于一个等待状态(不是暂停,一直处于网络实时监听),等待客户端找他进行连接。

       客户端连接:客户端对目标服务器发起链接请求,发起请求必须要知道IP以及相应端口号。

       确认链接:这个时候服务端的监听就起作用了,受到客户端的请求后会响应客户端请求,创建socket链接。在这里需要注意链接不是一对一的,服务端会重新对请求客户端创建新的socket服务。所以服务端仍处于监听状态仍可以监听。

代码示例

好了以上就是一些基本介绍,主要是为了以下的东西做铺垫,毕竟要实现需要有socket的基础,言归正传。下面开始我们完整的webSocket练习吧!(网上有些使用插件或者类库实现的websocket。但是我们所讲的是以socket为基础的)

创建服务器

别的不多少首先创建socket服务器:

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Net.Sockets; 7 using System.Net; 8 using System.Threading; 9 using System.Text.RegularExpressions;10 using System.Security.Cryptography;11 12 namespace SocketService13 {14     class SocketService15     {16         private static byte[] result = new byte[1024];17         private static int myProt = 8885;   //端口  18         static Socket serverSocket;  //服务器服务19         public void Start()20         {21             //服务器IP地址  22             IPAddress ip = IPAddress.Parse("127.0.0.1");23             //socket的构造函数进行服务注册24             serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);25             //绑定IP地址:端口  26             serverSocket.Bind(new IPEndPoint(ip, myProt));27             //设定最多10个排队连接请求 28             serverSocket.Listen(10);29             Console.WriteLine("启动监听{0}成功", serverSocket.LocalEndPoint.ToString());30             //通过Clientsoket发送数据  31             Thread myThread = new Thread(ListenClientConnect);32             myThread.Start();33             Console.ReadLine();34         }35         ///   36         /// 监听客户端连接  37         ///   38         private  void ListenClientConnect()39         {40             while (true)41             {42                 Socket clientSocket = serverSocket.Accept();43                // clientSocket.Send(Encoding.ASCII.GetBytes("Server Say Hello"));44                 Thread receiveThread = new Thread(ReceiveMessage);45                 receiveThread.Start(clientSocket);46             }47         }48 49         ///   50         /// 接收消息  51         ///   52         ///   53         private  void ReceiveMessage(object clientSocket)54         {55             Socket myClientSocket = (Socket)clientSocket;56             while (true)57             {58                 try59                 {60                     //通过clientSocket接收数据  61                     int receiveNumber = myClientSocket.Receive(result);62                     //  websocket建立连接的时候,除了TCP连接的三次握手,websocket协议中客户端与服务器想建立连接需要一次额外的握手动作63                     string msg = Encoding.UTF8.GetString(result, 0, receiveNumber);64                     var buffer = result;65                     if (msg.Contains("Sec-WebSocket-Key"))66                     {67 68                         myClientSocket.Send(PackageHandShakeData(buffer, receiveNumber));69 70                        // return;71                     }72                     var ss = AnalyzeClientData(result, receiveNumber);73                     Console.WriteLine("接收客户端{0}消息{1}", myClientSocket.RemoteEndPoint.ToString(), Encoding.UTF8.GetString(result, 0, receiveNumber));74                 }75                 catch (Exception ex)76                 {77                     Console.WriteLine(ex.Message);78                     myClientSocket.Shutdown(SocketShutdown.Both);79                     myClientSocket.Close();80                     break;81                 }82             }83         }84  }85 }
View Code

 代码注释我已经写的很详细了!希望你们能看懂(哈哈)!

 看到这里有些聪明的网友可能发现问题了!或者操作过但是没有成功的也看出了不同。没有错,在这里我要说明的一点是有些websocket与socket有点不同的就是他的握手的首次信息以及返回信息是需要特定格式的。

也就是所谓的响应头域需要特殊处理。在不做相对应的响应处理浏览器会报“握手不成功”的错误!

参考网址:http://www.cnblogs.com/smark/archive/2012/11/26/2789812.html 

如果初步同学没有看明白请移至另一篇博客,详细封装了此方法解决此错误。(方便有些同学查找错误找不到解决方法,因为鄙人也是搞了一上午才有幸发现此问题,还望海涵)

最后我们只需要在主方法进行调用开启服务

此时服务端代码大功告成!下面我们使用js来进行请求就可以了。

客户端

下面附送html建议代码也可以去w3c查看教程:

html代码:

javascript代码:

var ws;function WebSocketTest() {    if("WebSocket" in window) {        alert("您的浏览器支持 WebSocket!");        // 打开一个 web socket        ws = new WebSocket("ws://127.0.0.1:8885");        ws.onopen = function() {            // Web Socket 已连接上,使用 send() 方法发送数据            ws.send("发送数据");            alert("数据发送中...");        };        ws.onmessage = function(evt) {            var received_msg = evt.data;            document.getElementById("look").html+=received_msg;            alert("数据已接收...");        };        ws.onclose = function() {            // 关闭 websocket            alert("连接已关闭...");        };    } else {        // 浏览器不支持 WebSocket        alert("您的浏览器不支持 WebSocket!");    }}function webSocketClose() {ws.close();alert("关闭了通讯")}function send(){    var msg= document.getElementById("message").value;    if(msg==""||msg==undefined){        alert("请填写发送内容!")        return;    }    ws.send("1111111111");    alert("发送了消息")}
View Code

最后附上运行截图:

 

好了以上就是webSocket的一些基础介绍和简单的代码示例。

下一篇在此基础上完善成一个聊天示例:

作者: —— 颜秉锋

出处:
本文版权归作者和博客园共有,欢迎转载,转载请标明出处。如果您觉得本篇博文对您有所收获,觉得小弟还算用心,请点击右下角的 [推荐],谢谢!

你可能感兴趣的文章
redisson学习示例
查看>>
升级到 PHP 7.0
查看>>
error lnk2019 无法解析的外部符号
查看>>
ITSM--IT服务管理注意细则
查看>>
java list去重
查看>>
android中网络操作使用总结(http)
查看>>
JAVA中使用代码创建多数据源,并实现动态切换(一)
查看>>
理解Scroll View
查看>>
create instance 生成创建虚拟机从nova到调用libvirt流程(pycharm debug):
查看>>
第7章:Session简介
查看>>
django rest framework
查看>>
Another app is currently holding the yum lock; waiting for it to exit
查看>>
团队建设管理能力分析
查看>>
我的友情链接
查看>>
seafile安装
查看>>
Linux 系统text安装方法
查看>>
rsync 高级拷贝文件
查看>>
call to undefined function mb_convert_encoding
查看>>
Android Universal Image Loader 源码分析
查看>>
Laravel项目和其它项目共享session问题
查看>>