前言

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

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

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

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

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

WebSocket 是 HTML5
一种新的协议。它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯,它建立在
TCP 之上,同 HTTP 一样通过 TCP 来传输数据,但是它和 HTTP 最大不同是:

WebSocket 是 HTML5
一种新的协议。它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯,它建立在
TCP 之上,同 HTTP 一样通过 TCP 来传输数据,但是它和 HTTP 最大不同是:

什么是WebSocket 

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

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

与传统的HTTP协议对比:

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

1.WebSocket 是一种双向通信协议,在建立连接后,WebSocket 服务器和
Browser/Client Agent 都能主动的向对方发送或接收数据,就像 Socket 一样;

1.WebSocket 是一种双向通信协议,在建立连接后,WebSocket 服务器和
Browser/Client Agent 都能主动的向对方发送或接收数据,就像 Socket 一样;

WebSocket API介绍

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

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

2.WebSocket 需要类似 TCP
的客户端和服务器端通过握手连接,连接成功后才能相互通信。

2.WebSocket 需要类似 TCP
的客户端和服务器端通过握手连接,连接成功后才能相互通信。

WebSocket 对象属性

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

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

       相对于传统 HTTP
每次请求-应答都需要客户端与服务端建立连接的模式,WebSocket 是类似 Socket
的 TCP 长连接的通讯模式,一旦 WebSocket
连接建立后,后续数据都以帧序列的形式传输。在客户端断开 WebSocket 连接或
Server
端断掉连接前,不需要客户端和服务端重新发起连接请求。在海量并发及客户端与服务器交互负载流量大的情况下,极大的节省了网络带宽资源的消耗,有明显的性能优势,且客户端发送和接受消息是在同一个持久连接上发起,实时性优势明显。

   相对于传统 HTTP
每次请求-应答都需要客户端与服务端建立连接的模式,WebSocket 是类似 Socket
的 TCP 长连接的通讯模式,一旦 WebSocket
连接建立后,后续数据都以帧序列的形式传输。在客户端断开 WebSocket 连接或
Server
端断掉连接前,不需要客户端和服务端重新发起连接请求。在海量并发及客户端与服务器交互负载流量大的情况下,极大的节省了网络带宽资源的消耗,有明显的性能优势,且客户端发送和接受消息是在同一个持久连接上发起,实时性优势明显。

WebSocket 事件

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

Socket.onopen:连接建立时触发

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

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

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

WebSocket握手请求(使用http请求完成)

WebSocket握手请求(使用http请求完成)

WebSocket 方法

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

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

清单 1.WebSocket 客户端连接报文

清单 1.WebSocket 客户端连接报文

连接形式:

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

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

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

GET /webfin/websocket/ HTTP/1.1

GET /webfin/websocket/ HTTP/1.1

代码示例

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

Host: localhost

Host: localhost

创建服务器

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

图片 1图片 2

 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 SocketService
13 {
14     class SocketService
15     {
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         /// <summary>  
36         /// 监听客户端连接  
37         /// </summary>  
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         /// <summary>  
50         /// 接收消息  
51         /// </summary>  
52         /// <param name="clientSocket"></param>  
53         private  void ReceiveMessage(object clientSocket)
54         {
55             Socket myClientSocket = (Socket)clientSocket;
56             while (true)
57             {
58                 try
59                 {
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有点不同的就是他的握手的首次信息以及返回信息是需要特定格式的。

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

参考网址: 

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

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

图片 3

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

Upgrade: websocket

Upgrade: websocket

客户端

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

html代码:

    <body>
        <a href="javascript:WebSocketTest()">运行 WebSocket</a>
        <a href="javascript:webSocketClose()">关闭WebSocket</a>
        <div id="look" class="m">

        </div>
        <input id="message">
        <a href="javascript:send()">发送消息</a>
    </body>

javascript代码:

图片 4图片 5

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

最后附上运行截图:

图片 6

 图片 7

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

下一篇在此基础上完善成一个聊天示例:【WebSocket
No.2】WebSocket和Socket实现聊天群发

Connection: UpgradeSec-WebSocket-Key: xqBt3ImNzJbYqRINxEFlkg==

Connection: UpgradeSec-WebSocket-Key: xqBt3ImNzJbYqRINxEFlkg==

Origin:http://localhost:8080

Origin:http://localhost:8080

Sec-WebSocket-Version: 13

Sec-WebSocket-Version: 13

////”Upgrade:websocket”参数值表明这是 WebSocket
类型请求,WebSocket-Key”是 WebSocket 客户端发送的一个 base64
编码的密文,要求服务端必须返回一个对应加/密的“Sec-WebSocket-Accept”应答,否则客户端会抛出“Error
during WebSocket handshake”错误,并关闭连接。

////”Upgrade:websocket”参数值表明这是 WebSocket
类型请求,WebSocket-Key”是 WebSocket 客户端发送的一个 base64
编码的密文,要求服务端必须返回一个对应加/密的“Sec-WebSocket-Accept”应答,否则客户端会抛出“Error
during WebSocket handshake”错误,并关闭连接。

清单:2.WebSocket 服务端响应报文

清单:2.WebSocket 服务端响应报文

HTTP/1.1 101 Switching Protocols

HTTP/1.1 101 Switching Protocols

Upgrade: websocket

Upgrade: websocket

Connection: Upgrade

Connection: Upgrade

Sec-WebSocket-Accept: K7DJLdLooIwIG/MOpvWFB3y3FE8=

Sec-WebSocket-Accept: K7DJLdLooIwIG/MOpvWFB3y3FE8=

////“Sec-WebSocket-Accept”的值是服务端采用与客户端一致的密钥计算出来后返回客户端的,“HTTP/1.1
101 Switching Protocols”表示服务端接受 WebSocket 协议的客户端连接。

////“Sec-WebSocket-Accept”的值是服务端采用与客户端一致的密钥计算出来后返回客户端的,“HTTP/1.1
101 Switching Protocols”表示服务端接受 WebSocket 协议的客户端连接。

webSocket 客户端实例

// 创建一个Socket实例 

var socket = new WebSocket(‘ws://localhost:8080’);//服务器地址

// 打开Socket   

socket.onopen = function(event) {

// 发送一个初始化消息

socket.send(‘I am the client and I\’m listening!’);

// 监听消息

socket.onmessage = function(event) {

console.log(‘Client received a
message’,event);//???event.data???接收数据

};

// 监听Socket的关闭

socket.onclose = function(event) {

console.log(‘Client notified socket has closed’,event);

};

// 关闭Socket….

//socket.close()

webSocket 规范定义了ws和wss两种url模式,ws
用于非加密连接,wss用于加密连接。

webSocket 客户端实例

// 创建一个Socket实例

var socket = new WebSocket(‘ws://localhost:8080’);//服务器地址

// 打开Socket

socket.onopen = function(event) {

// 发送一个初始化消息

socket.send(‘I am the client and I\’m listening!’);

// 监听消息

socket.onmessage = function(event) {

console.log(‘Client received a
message’,event);//???event.data???接收数据

};

// 监听Socket的关闭

socket.onclose = function(event) {

console.log(‘Client notified socket has closed’,event);

};

// 关闭Socket….

//socket.close()

webSocket 规范定义了ws和wss两种url模式,ws
用于非加密连接,wss用于加密连接。

Author

发表评论

电子邮件地址不会被公开。 必填项已用*标注