精华内容
下载资源
问答
  • SpringMVC的Socket实现+Java Tomcat websocket实现+Java Socket通信实现 +Java UDP通信实现websocket_study.rar 为springMVC版本的socket实现 websocket02.rar 里面包含tomcat的websocket实现+java socket双向通信...
  • socket通信websocket通信协议

    千次阅读 2018-08-10 12:04:32
    socket通信 网络上的两个程序通过一个双向的通信链接实现数据的交换,这个链接的一端称为一个socket socket通信流程图 服务器端通过创建一个socket的通信链接,然后绑定socket和端口号并监听,就可以接收来自...

    socket通信

    1. 网络上的两个程序通过一个双向的通信链接实现数据的交换,这个链接的一端称为一个socket
    2. socket通信流程图

    通信流程图

    服务器端通过创建一个socket的通信链接,然后绑定socket和端口号并监听,就可以接收来自客户端的连接请求了,前提是客户端也有socket并且连接到了该服务器所在设备的端口。客户端通过send想socket中写入信息,服务器就可以读到。如果服务器关了,客户端程序是不能够正常登陆的。

              nodejs里面提供的net模块可以实现socket通信,因为它提供了一些用于底层的网络通信的小工具,包含了创建服务器/客户端的方法。

    //server.js
    //服务器文件
    var net = require("net");
    var server = new net.createServer;
    var clientObiect = {};
    //流水账号--区分服务器上的客户端
    var i = 0;
    //连接
    server.on("connection",(client)=>{
    	client.name = ++i;
    	clientObiect[client.name ]=client;
    	
    	client.on("data",(data)=>{
    		console.log("客户端发来:"+data);
    		huifu(client,data);
    	})
    	
    })
    function huifu(client,message){
    //	client.write("服务器已收到")	
    
    	for(let i in clientObiect){
    		clientObiect[i].write(client.name+"说:"+message);		
    	}
    	
    	
    }
    
    server.listen(3000)
    
    //client.js
    //客户端
    var net = require("net");
    var readline = require("readline");
    var socket = new net.Socket;
    var port = 3000;
    var hostname ="localhost";
    //var hostname ="10.8.162.15";
    //连接服务器
    socket.connect(port,hostname,()=>{
    	socket.write("超级无敌美少女已上线")	
    })
    //接收服务器数据
    socket.on("data",(data)=>{
    //	console.log("服务端发来:"+data)	
    	console.log(""+data)
    	say()
    })
    
    var r1 = new readline.createInterface({	
    	input:process.stdin,
    	output:process.stdout
    })
    
    function say(){
    	r1.question("请输入:",(str)=>{
    		socket.write(str)
    	})	
    }
    

    有了客户端和服务端,就可以通过node server  启动服务器,通过node client启动客户端(打开多个窗口,多个客户端),上面可以实现多个客户端程序之间的一个通信。改变端口号可以连接上其他计算机的服务器提供的端口,和其他客户端进行聊天。

    websocket通信

    • WebSocket是html5新增加的一种双工通信协议,目前流行的浏览器都支持这个协议

    它和socket不同的是,他属于前端的一个通信,和nodejs没啥关系。而socket是一个后端的通信协议,可以用来测试然后应用在客户端上。

    首先,npm init 创建一个依赖文件,再安装ws的一个依赖npm i ws -D,之后就可以去创建websocket里面的服务器和客户端了。

    服务器:

    //wsserver.js
    //服务器文件
    var wsserver = require("ws").Server;
    var wss = new wsserver({port:3000});
    var clientObiect = {};
    //流水账号---用来区分服务器上的客户端
    var i = 0;
    //连接
    wss.on("connection",(client)=>{
    	client.name = ++i;
    	clientObiect[client.name ]=client;	
    	client.on("message",(data)=>{
    		console.log("客户端发来:"+data);
    		huifu(client,data);
    	})
    })
    
    function huifu(client,message){
    
    	for(let i in clientObiect){
    		clientObiect[i].send(client.name+"说:"+message);		
    	}
    	
    }
    
    

    客户端:

    //demo.html
    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="UTF-8">
    		<title></title>
    		<style type="text/css">
    			*{
    				margin: 0;
    				padding: 0;
    			}
    			#con{
    				width: 500px;
    				height: 400px;
    				border: 1px solid red;
    			}
    			
    		</style>
    	</head>
    	<body>
    		<h1>h5通信</h1>
    		<div id="con"></div>
    		
    		<input type="text" id="ipt"/>
    		<button id="btn">发送</button>
    	</body>
    	<script type="text/javascript">
    //申请一个WebSocket对象,参数是需要连接服务器的地址,遵循的是ws协议
    		var client = new WebSocket('ws://localhost:3000');
    		client.onopen=function(){};
    		
    		client.onmessage =function(a){
    			document.getElementById("con").innerHTML+= "<p>"+a.data+"</p>"
    		}
    		
    		document.getElementById("btn").onclick=function(){
    			client.send(document.getElementById("ipt").value);
    			document.getElementById("ipt").value = "";
    		}
    		
    	</script>
    </html>
    

    WebSocket对象一共支持四个消息 onopen, onmessage, oncloseonerror

    • 当Browser和WebSocketServer连接成功后,会触发onopen消息;
    • 如果连接失败,发送、接收数据失败或者处理数据出现错误,browser会触发onerror消息;
    • 当Browser接收到WebSocketServer发送过来的数据时,就会触发onmessage消息,参数evt中包含server传输过来的数据;
    • 当Browser接收到WebSocketServer端发送的关闭连接请求时,就会触发onclose消息。

    我们可以看出所有的操作都是采用消息的方式触发的,这样就不会阻塞UI,使得UI有更快的响应时间,得到更好的用户体验。

    展开全文
  • 主要介绍了Vue+Java 通过websocket实现服务器客户端双向通信操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • socket服务端采用SuperSocket搭建,客户端服务端进行连接及向服务端发送消息,服务端使用业务向客户端发送消息进行通信
  • 使用Qt实现WebSocket客户端服务端之间的通信,可供初学者学习或使用
  • 二、WebSocket服务端功能实现 1、由于有使用到log4net,在开始实现功能前,需要对log4net进行相关设置,设置参考https://blog.csdn.net/liwan09/article/details/106266346 2、界面设置 3、实现功能代码 ...

    一、项目创建

    1、VS2017创建winform项目

    2、Nuget中搜索安装 SuperWebSocketNETServer

    二、WebSocket服务端功能实现

    1、由于有使用到log4net,在开始实现功能前,需要对log4net进行相关设置,设置参考https://blog.csdn.net/liwan09/article/details/106266346

    2、界面设置

     

    3、实现功能代码

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Web;
    using System.Windows.Forms;
    using SuperWebSocket;
    using log4net;
    using Bosch.Rtns.Sockect.Model;
    using Bosch.Rtns.Sockect.CommonUtils;
    
    namespace Bosch.Rtns.Sockect
    {
        public partial class frmMain : Form
        {
            private WebSocketServer webSocketServer;
            ILog loggerManager;
            Dictionary<WebSocketSession, string> socketSessionList = new Dictionary<WebSocketSession, string>();//记录链接的客户端数据
    
            public frmMain()
            {
                InitializeComponent();
            }
            /// <summary>
            /// load
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void frmMain_Load(object sender, EventArgs e)
            {
                loggerManager=LogManager.GetLogger("Logger");
                txtIPAddress.Text = "127.0.0.1";
                txtPort.Text = "1414";
                btnEnd.Enabled = false;
            }
            /// <summary>
            ///开启服务
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnStart_Click(object sender, EventArgs e)
            {
                string ipAddress = txtIPAddress.Text.Trim();
                string port = txtPort.Text.Trim();
                if (string.IsNullOrEmpty(ipAddress))
                {
                    txtIPAddress.Focus();
                    MessageBox.Show("请输入IP地址!");
                    return;
                }
                if (string.IsNullOrEmpty(port))
                {
                    txtPort.Focus();
                    MessageBox.Show("请输入端口号!");
                    return;
                }           
                webSocketServer = new WebSocketServer();
                webSocketServer.NewSessionConnected += Sockect_NewSessionConnected;
                webSocketServer.NewMessageReceived += Sockect_NewMessageReceived;
                webSocketServer.SessionClosed += Sockect_SessionClosed;
                if (!webSocketServer.Setup(ipAddress,Convert.ToInt32(port)))
                {
                    txtLogInfo.Text += "设置Socket服务侦听地址失败!\r\n";
                    loggerManager.Error("设置Socket服务侦听地址失败!\r\n");
                    return;
                }
                if (!webSocketServer.Start())
                {
                    txtLogInfo.Text += "启动WebSocket服务侦听失败!\r\n";
                    loggerManager.Error("启动WebSocket服务侦听失败!\r\n");
                    return;
                }
                txtLogInfo.Text += "Socket启动服务成功!\r\n";
                loggerManager.Info("Socket启动服务成功!\r\n");
                txtIPAddress.Enabled = false;
                txtPort.Enabled = false;
                btnStart.Enabled = false;
                btnEnd.Enabled = true;
            }
            /// <summary>
            /// 关闭服务
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnEnd_Click(object sender, EventArgs e)
            {
                if (webSocketServer != null)
                {
                    webSocketServer.Stop();
                    webSocketServer = null;
                }
                txtIPAddress.Enabled = true;
                txtPort.Enabled = true;
                btnStart.Enabled = true;
                btnEnd.Enabled = false;
            }
    
            /// <summary>
            /// 新的Socket连接事件
            /// </summary>
            /// <param name="session"></param>
            private void Sockect_NewSessionConnected(WebSocketSession session)
            {
                string logMsg = string.Format("{0} 与客户端{1}创建新会话", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), GetwebSocketSessionName(session))+"\r\n";            
                this.Invoke(new Action(() =>
                {
                    txtLogInfo.Text += logMsg;
                }));
                loggerManager.Info(logMsg);
                socketSessionList.Add(session, "");
            }
            /// <summary>
            /// 消息接收事件
            /// </summary>
            /// <param name="session"></param>
            /// <param name="value">接收的消息</param>
            private void Sockect_NewMessageReceived(WebSocketSession session, string value)
            {
                string logMsg = string.Format("{0} 从客户端{1}接收新的消息:\r\n{2}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), GetwebSocketSessionName(session),value) + "\r\n";
                this.Invoke(new Action(() =>
                {
                    txtLogInfo.Text += logMsg;
                }));
                loggerManager.Info(logMsg);
                ReceiveData receiveData = JsonHelper.ConvertToEntity<ReceiveData>(value);
                //退出登录
                if (receiveData.MessageType == "3")
                {
                    //调用weiapi接口,更新在线用户的在线状态
                    socketSessionList.Remove(session);
                    session.Close(SuperSocket.SocketBase.CloseReason.ClientClosing);//断开连接
                }
                else
                {
                    if(receiveData.MessageType == "4")//设备故障推送
                    {
                        EquipmentFault equipmentFault = JsonHelper.ConvertToEntity<EquipmentFault>(receiveData.MessageContent);
                    }
                    else
                    {
                        socketSessionList[session] = receiveData.MessageContent;//记录app端的设备id
                    }
                }
            }
            /// <summary>
            /// sockect客户端断开连接事件
            /// </summary>
            /// <param name="session"></param>
            /// <param name="value"></param>
            private void Sockect_SessionClosed(WebSocketSession session, SuperSocket.SocketBase.CloseReason value)
            {
                string logMsg = string.Format("{0} 与客户端{1}的会话被关闭 原因:{2}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), GetwebSocketSessionName(session), value) + "\r\n";
                this.Invoke(new Action(() =>
                {
                    txtLogInfo.Text += logMsg;
                }));
                loggerManager.Info(logMsg);
                socketSessionList.Remove(session);
            }
            /// <summary>
            /// 获取连接的客户端的ip地址
            /// </summary>
            /// <param name="webSocketSession"></param>
            private static string GetwebSocketSessionName(WebSocketSession webSocketSession)
            {
                string id= HttpUtility.UrlDecode(webSocketSession.SessionID);//获取sessionid
                var remoteClient = webSocketSession.RemoteEndPoint;
                return remoteClient.Address + ":" + remoteClient.Port.ToString();
            }
            /// <summary>
            /// 发送消息
            /// </summary>
            /// <param name="session"></param>
            /// <param name="msg"></param>
            private void SendMessage(WebSocketSession session, string msg)
            {
                //向所有客户端发送消息
                //foreach (var sendSession in session.AppServer.GetAllSessions())
                //{
                //    sendSession.Send(msg);
                //}
                session.Send(msg);//向指定的客户端发送消息
            }
        }
    }
    

     相关实体类代码

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Bosch.Rtns.Sockect.Model
    {
        /// <summary>
        /// 设备故障信息
        /// </summary>
        public class EquipmentFault
        {
            /// <summary>
            /// 目标手机设备ID
            /// </summary>
            public string TargetPhoneID { get; set; }
            /// <summary>
            /// 故障发生时间
            /// </summary>
            public DateTime FaultTime { get; set; }
            /// <summary>
            /// 消息id
            /// </summary>
            public string MessageUID { get; set; }
            /// <summary>
            /// 消息标题
            /// </summary>
            public string MessageTitle { get; set; }
            /// <summary>
            /// 发送给App(消息类型)
            /// </summary>
            public string SubAPPname { get; set; }
            /// <summary>
            /// 故障等级 Low,Default,High,Emergent
            /// </summary>
            public string EmergenceLevel { get; set; }
        }
    }
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Bosch.Rtns.Sockect.Model
    {
        /// <summary>
        /// 接收的消息
        /// </summary>
        public class ReceiveData
        {
            /// <summary>
            /// 接收的消息类型 1:App端登录  2:设备故障信息推送
            /// </summary>
            public string MessageType { get; set; }
            /// <summary>
            /// 消息内容
            /// </summary>
            public string MessageContent { get; set; }
        }
    }
    

    Json帮助类代码

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Newtonsoft.Json;
    
    namespace Bosch.Rtns.Sockect.CommonUtils
    {
        /// <summary>
        /// Json帮助类
        /// </summary>
        public class JsonHelper
        {
            /// <summary>
            /// object转json
            /// </summary>
            /// <param name="obj"></param>
            /// <returns></returns>
            public static string ConvertObjToJson(object obj)
            {
                return JsonConvert.SerializeObject(obj);
            }
            /// <summary>
            /// Json字符串转实体类数据
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="jsonValue"></param>
            /// <returns></returns>
            public static T ConvertToEntity<T>(string jsonValue)
            {
                return JsonConvert.DeserializeObject<T>(jsonValue);
            }
            /// <summary>
            /// Json字符串转List<T>
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="jsonValue"></param>
            /// <returns></returns>
            public static List<T> ConvertToList<T>(string jsonValue)
            {
                return JsonConvert.DeserializeObject<List<T>>(jsonValue);
            }
        }
    }
    

    4、客户端代码(html)

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <title>Web sockets test</title>
        <script src="jquery-min.js"></script>
    </head>
    <body>
        <div>
            服务器地址:<input type="text" id="serverAddress" value="127.0.0.1:4141" />
            <button type="button" onclick="connectionServer();">连接</button>
            <button type="button" onclick="DisconnectionServer()">断开</button>
        </div>
        <div>
            <button type="button" onclick="senMsg()">发送消息</button>
            <div>
                <textarea id="txtmsg" style="height:200px;width:300px"></textarea>
            </div>
        </div>
    </body>
    </html>
    <script type="text/javascript">
        var ws;
        var SocketCreated = false;
        var isUserloggedout = false;
        var defaultMsg = "{\"MessageType\":\"\",\"MessageContent\":\"\"}";
        document.getElementById("txtmsg").value = defaultMsg;
    
        function connectionServer() {
            try {
                if ("WebSocket" in window) {
                    ws = new WebSocket("ws://" + document.getElementById("serverAddress").value);
                }
                else if ("MozWebSocket" in window) {
                    ws = new MozWebSocket("ws://" + document.getElementById("serverAddress").value);
                }
                SocketCreated = true;
                isUserloggedout = false;
            } catch (ex) {
                alert("连接失败");
                return;
            }
        }
    
        function DisconnectionServer() {
            if (SocketCreated && (ws.readyState == 0 || ws.readyState == 1)) {
                SocketCreated = false;
                isUserloggedout = true;
                ws.close();
            }
        }
    
        function senMsg() {
            if (SocketCreated) {
                var msg = document.getElementById("txtmsg").value;
                ws.send(msg);
            }
        }
    </script>

     

    展开全文
  • WebSocket实现实时通信

    千次阅读 多人点赞 2021-07-23 14:31:31
    WebSocket 是一种数据通信协议,也是用于客户端和服务端数据通信,类似于我们常见的 http 既然有 http,为啥还要 WebSocket http 通信是单向的 请求 + 响应 没有请求也就没有响应 初次接触 WebSocket 的人,都会问...

    WebSocket 是一种数据通信协议,也是用于客户端和服务端数据通信,类似于我们常见的 http

    既然有 http,为啥还要 WebSocket
    http 通信是单向的
    请求 + 响应
    没有请求也就没有响应

    初次接触 WebSocket 的人,都会问同样的问题:我们已经有了 HTTP 协议,为什么还需要另一个协议?它能带来什么好处?

    答案很简单,因为 HTTP 协议有一个缺陷:通信只能由客户端发起。

    举例来说,我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息。

    这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。我们只能使用"轮询":每隔一段时候,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。

    轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。因此,工程师们一直在思考,有没有更好的方法。WebSocket 就是这样发明的。

    WebSocket 协议在 2008 年诞生,2011 年成为国际标准。所有浏览器都已经支持了。

    它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。

    简单理解:

    1. HTTP 打电话:
      我问一句
      你回答一句
      没有提问就没有回答,即便对方主动给你说话,我也是个聋子听不见

    2. WebSocket 打电话:
      双向对话
      在这里插入图片描述

    HTTP 和 WebSocket 通信模型

    其他特点包括:

    (1)和 HTTP 一样属于应用层协议,也是建立在 TCP 协议之上,服务器端的实现比较容易。

    (2)与 HTTP 协议有着良好的兼容性。默认端口也是 80 和 443,并且握手阶段(第 1 次建立连接)采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

    (3)数据格式比较轻量,性能开销小,通信高效。

    (4)可以发送文本,也可以发送二进制数据。

    (5)没有同源跨域限制,客户端可以与任意服务器通信。

    WebSocket 不是用来代替 HTTP 的,它是用来解决实时通信的业务场景。如果业务不需要实时性,那就没必要使用 WebSocket。

    WebSocket 也是有资源消耗的,因为它要实时通信,也是需要和服务端保持一定的通信连接。

    WebSocket 也是需要服务端配合才能使用。

    (6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

    (7)浏览器专门为 WebSocket 通信提供了一个请求对象 WebSocket

    XmlHttPRequest 请求对象,发起 HTTP 协议请求

    ws://example.com:80/some/path
    
    http https
    ws   wss
    

    使用原生 WebSocket(了解)

    参考文档:

    MDN - WebSocket

    浏览器为 HTTP 通信提供了 XMLHttpRequest 对象,同样的,也为 WebSocket 通信提供了一个通信操作接口:WebSocket。

    通信模型:

    拨号(建立连接)
    通话(双向通信)
    结束通话(关闭连接)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
    <script>
      // WebSocet 通信模型
    
      // 1. 拨打电话(建立连接)
      // 注意:wss://echo.websocket.org 是一个在线的测试接口,仅用于 WebSocket 协议通信测试使用
      var ws = new WebSocket("wss://echo.websocket.org");
    
      // 当连接建立成功,触发 open 事件
      ws.onopen = function(evt) {
        console.log("建立连接成功 ...");
    
        // 连接建立成功以后,就可以使用这个连接对象通信了
        // send 方法发送数据
        ws.send("Hello WebSockets!");
      };
    
      // 当接收到对方发送的消息的时候,触发 message 事件
      // 我们可以通过回调函数的 evt.data 获取对方发送的数据内容
      ws.onmessage = function(evt) {
        console.log("接收到消息: " + evt.data);
    
        // 当不需要通信的时候,可以手动的关闭连接
        // ws.close();
      };
    
      // 当连接断开的时候触发 close 事件
      ws.onclose = function(evt) {
        console.log("连接已关闭.");
      }
    </script>
    </body>
    </html>
    
    

    在这里插入图片描述
    怎么查看 WebSocket 请求日志?
    在这里插入图片描述
    朝上的绿色箭头是发出去的消息

    朝下的红色箭头是收到的消息

    展开全文
  • WebSocket Socket.IO

    2019-10-07 08:56:51
    最近小组在做一个智慧交通的项目,其中有个 “分享屏幕” 的功能,即一个 client 能够将自己当前的页面分享到另外一个 client,针对这个需求,我们利用了 WebSocket 技术,具体说是Socket.IO。 1. 什么是 WebSocket...

    综述:在做小程序和电视端互动项目时,也使用了socket.io十分重要的内容。

    最近小组在做一个智慧交通的项目,其中有个 “分享屏幕” 的功能,即一个 client 能够将自己当前的页面分享到另外一个 client,针对这个需求,我们利用了 WebSocket 技术,具体说是 Socket.IO

    1. 什么是 WebSocket

    提到 WebSocket,我首先会想到 “及时通讯” 和 “推送” 这类词。在 WebSocket 以前,很多网站通过其他方式来推送信息,下面我们先看看以前的推送方式,这样,有比较才能看出 WebSocket 的优势。

    1.1 (短)轮询(Polling)

    这种方式下,client 每隔一段时间都会向 server 发送 http 请求,服务器收到请求后,将最新的数据发回给 client。一开始必须通过提交表单的形式,这样的后果就是传输很多冗余的数据,浪费了带宽。后来 Ajax 出现,减少了传输数据量。

    如图所示,在 client 向 server 发送一个请求活动结束后,server 中的数据发生了改变,所以 client 向 server 发送的第二次请求中,server 会将最新的数据返回给 client。

    但这种方式也存在弊端。比如在某个时间段 server 没有更新数据,但 client 仍然每隔一段时间发送请求来询问,所以这段时间内的询问都是无效的,这样浪费了网络带宽。将发送请求的间隔时间加大会缓解这种浪费,但如果 server 更新数据很快时,这样又不能满足数据的实时性。

    1.2 Comet

    鉴于(短)轮询的弊端,一种基于 HTTP 长连接的 “服务器推” 的技术被 hack 了出来,这种技术被命名为 Comet。其与(短)轮询主要区别就是,在轮询方式下,要想取得数据,必须首先发送请求,在实时性要求较高的情况下,只能增加向 server 请求的频率;而 Comet 则不同,client 与 server 端保持一个长连接,只有数据发生改变时,server 才主动将数据推送给 client。Comet 又可以被细分为两种实现方式,一种是长轮询机制,一种是流技术。

    1.2.1 长轮询(Long-polling)

    client 向 server 发出请求,server 接收到请求后,server 并不一定立即发送回应给 client,而是看数据是否更新,如果数据已经更新了的话,那就立即将数据返回给 client;但如果数据没有更新,那就把这个请求保持住,等待有新的数据到来时,才将数据返回给 client。

    当然了,如果 server 的数据长时间没有更新,一段时间后,请求便会超时,client 收到超时信息后,再立即发送一个新的请求给 server。

    如图所示,在长轮询机制下,client 向 server 发送了请求后,server会等数据更新完才会将数据返回,而不是像(短)轮询一样不管数据有没有更新然后立即返回。

    这种方式也有弊端。当 server 向 client 发送数据后,必须等待下一次请求才能将新的数据发送出去,这样 client 接收到新数据的间隔最短时间便是 2 * RTT(往返时间),这样便无法应对 server 端数据更新频率较快的情况。

    1.2.2 流技术(Http Streaming)

    流技术基于 Iframe。Iframe 是 HTML 标记,这个标记的 src 属性会保持对指定 server 的长连接请求,server 就可以不断地向 client 返回数据。

    可以看出,流技术与长轮询的区别是长轮询本质上还是一种轮询方式,只不过连接的时间有所增加,想要向 server 获取新的数据,client 只能一遍遍的发送请求;而流技术是一直保持连接,不需要 client 请求,当数据发生改变时,server 自动的将数据发送给 client。

    如图所示,client 与 server 建立连接之后,便不会断开。当数据发生变化,server 便将数据发送给 client。

    但这种方式有一个明显的不足之处,网页会一直显示未加载完成的状态,虽然我没有强迫症,但这点还是难以忍受。

    1.3 WebSocket

    写到现在,大家会发现,前人推出那么多的解决方案,想要解决的唯一的问题便是怎么让 server 将最新的数据以最快的速度发送给 client。但 HTTP 是个懒惰的协议,server 只有收到请求才会做出回应,否则什么事都不干。因此,为了彻底解决这个 server 主动向 client 发送数据的问题,W3C 在 HTML5 中提供了一种 client 与 server 间进行全双工通讯的网络技术 WebSocket。WebSocket 是一个全新的、独立的协议,基于 TCP 协议,与 HTTP 协议兼容却不会融入 HTTP 协议,仅仅作为 HTML5 的一部分。

    那 WebSocket 与 HTTP 什么关系呢?简单来说,WebSocket 是一种协议,是一种与 HTTP 同等的网络协议,两者都是应用层协议,都基于 TCP 协议。但是 WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 server 与 client 都能主动向对方发送或接收数据。同时,WebSocket 在建立连接时需要借助 HTTP 协议,连接建立好了之后 client 与 server 之间的双向通信就与 HTTP 无关了。

    2. WebSocket 原理

    相比于传统 HTTP 的每次“请求-应答”都要 client 与 server 建立连接的模式,WebSocket 是一种长连接的模式。具体什么意思呢?就是一旦 WebSocket 连接建立后,除非 client 或者 server 中有一端主动断开连接,否则每次数据传输之前都不需要 HTTP 那样请求数据。从上面的图可以看出,client 第一次需要与 server 建立连接,当 server 确认连接之后,两者便一直处于连接状态。直到一方断开连接,WebSocket 连接才断开。

    下面我们从报文层面谈一下 WebSocket 与 HTTP 的差异。

    首先,client 发起 WebSocket 连接,报文类似于 HTTP,但主要有几点不一样的地方:

    • "Upgrade: websocket": 表明这是一个 WebSocket 类型请求,意在告诉 server 需要将通信协议切换到 WebSocket

    • "Sec-WebSocket-Key: *": 是 client 发送的一个 base64 编码的密文,要求 server 必须返回一个对应加密的 "Sec-WebSocket-Accept" 应答,否则 client 会抛出 "Error during WebSocket handshake" 错误,并关闭连接

    server 收到报文后,如果支持 WebSocket 协议,那么就会将自己的通信协议切换到 WebSocket,返回以下信息:

    • "HTTP/1.1 101 WebSocket Protocol Handshake":返回的状态码为 101,表示同意 client 的协议转换请求

    • "Upgrade: websocket"

    • "Connection: Upgrade"

    • "Sec-WebSocket-Accept: *"

    • ...

    以上都是利用 HTTP 协议完成的。这样,经过“请求-相应”的过程, server 与 client 的 WebSocket 连接握手成功,后续便可以进行 TCP 通讯了,也就没有 HTTP 什么事了。可以查阅WebSocket 协议栈了解 WebSocket 的 client 与 server 更详细的交互数据格式。

    3. WebSocket 与 Socket

    网络应用中,两个应用程序同时需要向对方发送消息的能力(即全双工通信),所利用到的技术就是 socket,其能够提供端对端的通信。对于程序员而言,其需要在 A 端创建一个 socket 实例,并为这个实例提供其所要连接的 B 端的 IP 地址和端口号,而在 B 端创建另一个 socket 实例,并且绑定本地端口号来进行监听。当 A 和 B 建立连接后,双方就建立了一个端对端的 TCP 连接,从而可以进行双向通信。

    WebSocekt 是 HTML5 规范中的一部分,其借鉴了 socket 的思想,为 client 和 server 之间提供了类似的双向通信机制。同时,WebSocket 又是一种新的应用层协议,包含一套标准的 API;而 socket 并不是一个协议,而是一组接口,其主要方便大家直接使用更底层的协议(比如 TCP 或 UDP)

    4. 什么是 Socket.IO

    Socket.IO 是一个封装了 Websocket、基于 Node 的 JavaScript 框架,包含 client 的 JavaScript 和 server 的 Node。其屏蔽了所有底层细节,让顶层调用非常简单。

    另外,Socket.IO 还有一个非常重要的好处。其不仅支持 WebSocket,还支持许多种轮询机制以及其他实时通信方式,并封装了通用的接口。这些方式包含 Adobe Flash Socket、Ajax 长轮询、Ajax multipart streaming 、持久 Iframe、JSONP 轮询等。换句话说,当 Socket.IO 检测到当前环境不支持 WebSocket 时,能够自动地选择最佳的方式来实现网络的实时通信。

    参考:

    1. Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE

    2. 微信公众号: 【龙果】 --- 《WebSocket --web持久连接神器》

    3. WebSocket详解(一):初步认识WebSocket技术

    4. Socket 与 WebSocket

    5. Differences between socket.io and websockets

    展开全文
  • 本篇文章主要介绍了使用 Spring Boot 实现 WebSocket实时通信,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • WebSocket Socket 的区别

    千次阅读 2019-03-26 11:48:04
    WebSocket Socket 的区别 准备:如果不太了解网络的朋友可以先看一下我之前写的文章 需要了解的网络协议 。 想必大家再做即时通讯业务或需要替代轮训的时候,肯定听说过 WebSocketSocket 这两个东西,我们...
  • MFC socket与websocket通信

    2016-11-20 20:04:50
    所传文档为MFC的SOCKET协议HTML5里的WEBSOCKET协议之间的通信连接,发送和读写都没有什么问题,另外附带有一个C#的websocket库,库不是开源的,网上也有详细介绍,如果想用C++这块的可以看看,有什么问题可以直接...
  • 1、socket翻译为套接字,socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用以实现进程在网络中通信。 2、WebSocket协议是基于TCP的一种新的网络协议,和http协议...
  • c++ websocket与js实现通信

    千次阅读 2019-07-08 19:39:23
    开发库:boost、websocketpp。 开发语言:c++web(html、js)
  • c++ socket实现http及websocket通信

    千次阅读 2020-05-20 20:50:11
    最近由于工程需要,需要在本地实现网页本地程序实时通信,但网页又不能直接通过socket与本地程序通信,只能支持相关的web协议,经过考虑我选择了http与websocket协议,这样的话就要实现本地服务器,网上有很多开源...
  • 本文实例讲述了nodejs结合socket.io实现websocket通信功能的方法。分享给大家供大家参考,具体如下: 因为项目中有需要实时获取后台数据的场景,之前一直是使用http心跳请求的方法。因为websocket与此模式相比有很大...
  • netty学习—实现websocket长连接和socket之间通信 ...项目目标:客户端A(网页)和服务端通过WebSocket进行通信,客户端B和服务端通过Socket通信,把客户端B的数据传输到客户端A,桥梁为服务端 Socket服务端监听8090...
  • 这里,介绍如何使用 Python 前端 js 进行通信websocket 使用 HTTP 协议完成握手之后,不通过 HTTP 直接进行 websocket 通信。 于是,使用 websocket 大致两个步骤:使用 HTTP 握手,通信。 js 处理 websocket ...
  • 点击关注公众号,利用碎片时间学习WebSocket介绍原理WebSocket protocol 是HTML5一种新的协议。它实现了浏览器服务器全双工通信(full-duplex)。一开...
  • 利用C++ SOCKET编程,自我实现的一个websocket服务器,能够比较好的移植,没有使用开源库
  • 2.System.Net.Sockets.Socket,也能写一套较好的服务器端。在.NET 4.5之前用较多,使用起来麻烦。需要对数据包进行解析等操作(但貌似网上有对超长包的处理方法) 3.System.Net.WebSockets.WebSocket,这个,是.NET ...
  • 之前用java jsp写过一个聊天,其实实现逻辑并不难,只是大部分时间都用在UI的设计上,其实现原理就是一个基于websocket通信,要想做一个好的聊天室,我觉得大部分精力可能更应该花在用户的视觉层交互上。...
  • import socket import threading from flask import Flask from flask_sockets import Sockets from gevent import pywsgi from geventwebsocket.handler import WebSocketHandler app = Flask(__name__) sockets...
  • socket.io能为程序员提供客户端和服务端一致的编程体验,socket.io支持任何的浏览器,任何的Mobile设备。下面通过本篇文章给大家讲解HTML5之WebSocket入门3 -通信模型socket.io,需要的朋友可以参考下
  • 摘 要随着网络通信和计算机技术的发展,人们越来越希望能够即时发送和接收互联网消息。与此同时随着互联网的发展在HTML5中提出了websocket协议,能更好的节省服务器资源和带宽并且服务器和浏览器能够双向实时通讯。...
  • WebSocketSocket

    2020-06-22 12:34:54
    实现了浏览器服务器全双工通信(full-duplex)。一开始的握手需要借助HTTP请求完成。 目的:即时通讯,替代轮询 应用场景:网站上的即时通讯是很常见的,比如网页的QQ,聊天系统等。按照以往的技术能力通常是...
  • 客户端使用websocket,服务器使用Java Socket。客户端经过new webSocket(utl)之后,服务器端可以收到请求头,但是客户端的webSocket.readyState一直是0,没有连接成功,这个是因为什么呢?是不是因为服务器端不可以...
  • 一文读懂 WebSocket 通信过程与实现

    万次阅读 2018-05-14 22:12:23
    什么是 WebSocketWebSocket 是一种标准协议,用于在客户端和服务端之间进行双向数据传输。但它跟 HTTP 没什么关系,它是一种基于 TCP 的一种独立实现。以前客户端想知道服务端的处理进度,要不停地使用 Ajax 进行...
  • WebSocket Socket TCP/UDP

    2018-11-24 13:53:01
    WebSocket Socket通信源码例子,TCP/UDP都有,适合网络通信入门的练习学习,有一个在线的聊天室系统
  • 基于nodejs-websocket模块、Socket.io库实现多人在线聊天室[丰富了上传图片,发送表情等实用聊天功能]
  • websocket 是一种网络通信协议,一般用来进行实时通信会使用到。。。 什么是socket.io?socket.io是一个高性能高可靠的websocket库,后端server基于node.js,前端提供多语言client。。。本文通过一个聊天功能实战,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 22,138
精华内容 8,855
关键字:

websocket与socket实现通信