【转】WebSocket详解(一):初步认识WebSocket技术

1、前言


HTML5规范在传统的web交互基础上为我们带来了众多的新特性,随着web技术被广泛用于web APP的开发,这些新特性得以推广和使用,而websocket作为一种新的web通信技术具有巨大意义。

本文将带您认识WebSocket。也可查看本文的下篇:《WebSocket详解(二):技术原理、代码演示和应用案例》。

2、系列文章


本文是系列文章中的第1篇,本系列文章的大纲如下:
 
  • 《WebSocket详解(一):初步认识WebSocket技术》(本文
  • 《WebSocket详解(二):技术原理、代码演示和应用案例》
  • 《WebSocket详解(三):深入WebSocket通信协议细节》
  • 《WebSocket详解(四):刨根问底HTTP与WebSocket的关系(上篇)》
  • 《WebSocket详解(五):刨根问底HTTP与WebSocket的关系(下篇)》
  • 《WebSocket详解(六):刨根问底WebSocket与Socket的关系》
 

3、更多资料


Web端即时通讯新手入门贴:
《新手入门贴:详解Web端即时通讯技术的原理》

Web端即时通讯技术盘点请参见:
《Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE》

关于Ajax短轮询:
找这方面的资料没什么意义,除非忽悠客户,否则请考虑其它3种方案即可。

有关Comet技术的详细介绍请参见:
《Comet技术详解:基于HTTP长连接的Web端实时通信技术》
《WEB端即时通讯:HTTP长连接、长轮询(long polling)详解》
《WEB端即时通讯:不用WebSocket也一样能搞定消息的即时性》
《开源Comet服务器iComet:支持百万并发的Web端即时通讯方案》

更多WebSocket的详细介绍请参见:
《WebSocket从入门到精通,半小时就够!》
《新手快速入门:WebSocket简明教程》
《理论联系实际:从零理解WebSocket的通信原理、协议格式、安全性》
《八问WebSocket协议:为你快速解答WebSocket热门疑问》
《Socket.IO介绍:支持WebSocket、用于WEB端的即时通讯的框架》
《socket.io和websocket 之间是什么关系?有什么区别?》
《Web端即时通讯实践干货:如何让你的WebSocket断网重连更快速?》

有关SSE的详细介绍文章请参见:
《SSE技术详解:一种全新的HTML5服务器推送事件技术》

更多WEB端即时通讯文章请见:
http://www.52im.net/forum.php?mod=collection&action=view&ctid=15

4、什么是Socket?什么是WebSocket?


对于第1次听说WebSocket技术的人来说,两者有什么区别?websocket是仅仅将socket的概念移植到浏览器中的实现吗?

我们知道,在网络中的两个应用程序(进程)需要全双工相互通信(全双工即双方可同时向对方发送消息),需要用到的就是socket,它能够提供端对端通信,对于程序员来讲,他只需要在某个应用程序的一端(暂且称之为客户端)创建一个socket实例并且提供它所要连接一端(暂且称之为服务端)的IP地址和端口,而另外一端(服务端)创建另一个socket并绑定本地端口进行监听,然后客户端进行连接服务端,服务端接受连接之后双方建立了一个端对端的TCP连接,在该连接上就可以双向通讯了,而且一旦建立这个连接之后,通信双方就没有客户端服务端之分了,提供的就是端对端通信了。我们可以采取这种方式构建一个桌面版的im程序,让不同主机上的用户发送消息。从本质上来说,socket并不是一个新的协议,它只是为了便于程序员进行网络编程而对tcp/ip协议族通信机制的一种封装。

websocket是html5规范中的一个部分,它借鉴了socket这种思想,为web应用程序客户端和服务端之间(注意是客户端服务端)提供了一种全双工通信机制。同时,它又是一种新的应用层协议,websocket协议是为了提供web应用程序和服务端全双工通信而专门制定的一种应用层协议,通常它表示为:ws://echo.websocket.org/?encoding=text HTTP/1.1,可以看到除了前面的协议名和http不同之外,它的表示地址就是传统的url地址。

可以看到,websocket并不是简单地将socket这一概念在浏览器环境中的移植,本文最后也会通过一个小的demo来进一步讲述socket和websocket在使用上的区别。

5、WebSocket的通信原理和机制


既然是基于浏览器端的web技术,那么它的通信肯定少不了http,websocket本身虽然也是一种新的应用层协议,但是它也不能够脱离http而单独存在。具体来讲,我们在客户端构建一个websocket实例,并且为它绑定一个需要连接到的服务器地址,当客户端连接服务端的时候,会向服务端发送一个类似下面的http报文:

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

可以看到,这是一个http get请求报文,注意该报文中有一个upgrade首部,它的作用是告诉服务端需要将通信协议切换到websocket,如果服务端支持websocket协议,那么它就会将自己的通信协议切换到websocket,同时发给客户端类似于以下的一个响应报文头:

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

返回的状态码为101,表示同意客户端协议转换请求,并将它转换为websocket协议。以上过程都是利用http通信完成的,称之为websocket协议握手(websocket Protocol handshake),进过这握手之后,客户端和服务端就建立了websocket连接,以后的通信走的都是websocket协议了。所以总结为websocket握手需要借助于http协议,建立连接后通信过程使用websocket协议。同时需要了解的是,该websocket连接还是基于我们刚才发起http连接的那个TCP连接。一旦建立连接之后,我们就可以进行数据传输了,websocket提供两种数据传输:文本数据和二进制数据。

基于以上分析,我们可以看到,websocket能够提供低延迟,高性能的客户端与服务端的双向数据通信。它颠覆了之前web开发的请求处理响应模式,并且提供了一种真正意义上的客户端请求,服务器推送数据的模式,特别适合实时数据交互应用开发。

6、WebSocket技术出现之前,Web端实现即时通讯的方法有哪些?

 

6.1定期轮询的方式


客户端按照某个时间间隔不断地向服务端发送请求,请求服务端的最新数据然后更新客户端显示。这种方式实际上浪费了大量流量并且对服务端造成了很大压力。
 

6.2SSE(Server-Sent Event,服务端推送事件)


SSE(Server-Sent Event,服务端推送事件)是一种允许服务端向客户端推送新数据的HTML5技术。与由客户端每隔几秒从服务端轮询拉取新数据相比,这是一种更优的解决方案。

相较于WebSocket,它也能从服务端向客户端推送数据。WebSocket能做的,SSE也能做,反之亦然,但在完成某些任务方面,它们各有千秋。关于SSE的介绍,即时通讯网将在稍后的文章中详细介绍。
 

6.3Comet技术


Comet并不是一种新的通信技术,它是在客户端请求服务端这个模式上的一种hack技术,通常来讲,它主要分为以下两种做法:

(1)基于长轮询的服务端推送技术
具体来讲,就是客户端首先给服务端发送一个请求,服务端收到该请求之后如果数据没有更新则并不立即返回,服务端阻塞请求的返回,直到数据发生了更新或者发生了连接超时,服务端返回数据之后客户端再次发送同样的请求,如下所示:
WebSocket详解(一):初步认识WebSocket技术_a.png

(2)基于流式数据传输的长连接
通常的做法是在页面中嵌入一个隐藏的iframe,然后让这个iframe的src属性指向我们请求的一个服务端地址,并且为了数据更新,我们将页面上数据更新操作封装为一个js函数,将函数名当做参数传递到这个地址当中。

服务端收到请求后解析地址取出参数(客户端js函数调用名),每当有数据更新的时候,返回对客户端函数的调用,并且将要跟新的数据以js函数的参数填入到返回内容当中,例如返回“<script type="text/javascript">update("data")</script>”这样一个字符串,意味着以data为参数调用客户端update函数进行客户端view更新。基本模型如下所示:
WebSocket详解(一):初步认识WebSocket技术_b.png

可以看到comet技术是针对客户端请求服务器响应模型而模拟出的一个服务端推送数据实时更新技术。而且由于浏览器兼容性不能够广泛应用。
 

6.4小结


当然并不是说这些技术没有用,就算websocket已经作为规范被提出并实现,但是对于老式浏览器,我们依然需要将它降级为以上方式来实现实时交互和服务端数据推送。

7、一个简单的WebSocket聊天小例子


到此为止,我们明白了websocket的原理,下面通过一个简单的聊天应用来再次加深下对websocket的理解。该应用需求很简单,就是在web选项卡中打开两个网页,模拟两个web客户端实现聊天功能。
 

7.1客户端代码


client.html:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .message{
            width: 60%;
            margin: 0 10px;
            display: inline-block;
            text-align: center;
            height: 40px;
            line-height: 40px;
            font-size: 20px;
            border-radius: 5px;
            border: 1px solid #B3D33F;
        }
        .form{
            width:100%;
            position: fixed;
            bottom: 300px;
            left: 0;
        }
        .connect{
            height: 40px;
            vertical-align: top;
            /* padding: 0; */
            width: 80px;
            font-size: 20px;
            border-radius: 5px;
            border: none;
            background: #B3D33F;
            color: #fff;
        }
    </style>
</head>
<body>
<ul id="content"></ul>
<form class="form">
<input type="text" placeholder="请输入发送的消息" class="message" id="message"/>
<input type="button" value="发送" id="send" class="connect"/>
<input type="button" value="连接" id="connect" class="connect"/>
</form>
<script></script>
</body>
</html>

客户端js代码:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var oUl=document.getElementById('content');
    var oConnect=document.getElementById('connect');
    var oSend=document.getElementById('send');
    var oInput=document.getElementById('message');
    var ws=null;
    oConnect.onclick=function(){
        ws=new WebSocket('ws://localhost:5000');
         ws.onopen=function(){
             oUl.innerHTML+="<li>客户端已连接</li>";
         }
        ws.onmessage=function(evt){
            oUl.innerHTML+="<li>"+evt.data+"</li>";
        }
        ws.onclose=function(){
            oUl.innerHTML+="<li>客户端已断开连接</li>";
        };
        ws.onerror=function(evt){
            oUl.innerHTML+="<li>"+evt.data+"</li>";
        };
    };
    oSend.onclick=function(){
        if(ws){
            ws.send(oInput.value);
        }
    }

这里使用的是w3c规范中关于HTML5 websocket API的原生API,这些api很简单,就是利用new WebSocket创建一个指定连接服务端地址的ws实例,然后为该实例注册onopen(连接服务端),onmessage(接受服务端数据),onclose(关闭连接)以及ws.send(建立连接后)发送请求。上面说了那么多,事实上可以看到html5 websocket API本身是很简单的一个对象和它的几个方法而已。
 

7.2服务端代码


服务端采用Node.js,这里需要基于一个nodejs-websocket的Node.js服务端的库,它是一个轻量级的Node.js websocket server端的实现,实际上也是使用Node.js提供的net模块写成的。

server.js:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var app=require('http').createServer(handler);
var ws=require('nodejs-websocket');
var fs=require('fs');
app.listen(80);
function handler(req,res){
    fs.readFile(__dirname+'/client.html',function(err,data){
        if(err){
            res.writeHead(500);
            return res.end('error ');
        }
        res.writeHead(200);
        res.end(data);
    });
}
var server=ws.createServer(function(conn){
    console.log('new conneciton');
    conn.on("text",function(str){
        broadcast(server,str);
    });
    conn.on("close",function(code,reason){
        console.log('connection closed');
    })
}).listen(5000);
function broadcast(server, msg) {
    server.connections.forEach(function (conn) {
        conn.sendText(msg);
    })
}

首先利用http模块监听用户的http请求并显示client.html界面,然后创建一个websocket服务端等待用户连接,在接收到用户发送来的数据之后将它广播到所有连接到的客户端。
 

7.3运行


下面我们打开两个浏览器选项卡模拟两个客户端进行连接。

客户端一发起连接:
WebSocket详解(一):初步认识WebSocket技术_x1.png

客户端一请求响应报文如下:
WebSocket详解(一):初步认识WebSocket技术_x2.png

可以看到这次握手和我们之前讲的如出一辙。

客户端二的连接过程和1是一样的,这里为了查看我们使用ff浏览器,两个客户端的连接情况如下:
WebSocket详解(一):初步认识WebSocket技术_x3.jpg

发送消息情况如下:
WebSocket详解(一):初步认识WebSocket技术_x4.png

可以看到,双方发送的消息被服务端广播给了每个和自己连接的客户端。

8、结语


从上面的即时通讯聊天例子我们可以看到,要想做一个点对点的im应用,websocket采取的方式是让所有客户端连接服务端,服务器将不同客户端发送给自己的消息进行转发或者广播,而对于原始的socket,只要两端建立连接之后,就可以发送端对端的数据,不需要经过第三方的转发(即时通讯网注:原文作者指的是原生的Socket可以通过P2P直接进行消息交互,实际现今主流的IM应用几乎都是使用服务端中转的方式进行文本类消息的发送,使用中转无关技术,主要是基于运营考虑),这也是websocket不同于socket的一个重要特点。

最后,本文为了说明html5规范中的websocket在客户端采用了websocket原生的API,实际开发中,有比较著名的两个库socket.io和sockjs,它们都对原始的websocket API做了进一步封装,提供了更多功能,都分为客户端和服务端的实现,实际应用中,可以选择使用。

如果您觉得本文还是显得有点专业,可以看看知乎上的这篇《WebSocket 是什么原理?为什么可以实现持久连接?》,比较通俗,适合快餐式地了解WebSocket。

附录:全站即时通讯技术资料分类


[1] 网络编程基础资料:
《TCP/IP详解 - 第11章·UDP:用户数据报协议》
《TCP/IP详解 - 第17章·TCP:传输控制协议》
《TCP/IP详解 - 第18章·TCP连接的建立与终止》
《TCP/IP详解 - 第21章·TCP的超时与重传》
《理论经典:TCP协议的3次握手与4次挥手过程详解》
《理论联系实际:Wireshark抓包分析TCP 3次握手、4次挥手过程》
《计算机网络通讯协议关系图(中文珍藏版)》
《NAT详解:基本原理、穿越技术(P2P打洞)、端口老化等》
《UDP中一个包的大小最大能多大?》
《Java新一代网络编程模型AIO原理及Linux系统AIO介绍》
《NIO框架入门(三):iOS与MINA2、Netty4的跨平台UDP双向通信实战》
《NIO框架入门(四):Android与MINA2、Netty4的跨平台UDP双向通信实战》
>> 更多同类文章 ……

[2] 有关IM/推送的通信格式、协议的选择:
《为什么QQ用的是UDP协议而不是TCP协议?》
《移动端即时通讯协议选择:UDP还是TCP?》
《如何选择即时通讯应用的数据传输格式》
《强列建议将Protobuf作为你的即时通讯应用数据传输格式》
《移动端IM开发需要面对的技术问题(含通信协议选择)》
《简述移动端IM开发的那些坑:架构设计、通信协议和客户端》
《理论联系实际:一套典型的IM通信协议设计详解》
《58到家实时消息系统的协议设计等技术实践分享》
>> 更多同类文章 ……

[3] 有关IM/推送的心跳保活处理:
《Android进程保活详解:一篇文章解决你的所有疑问》
《Android端消息推送总结:实现原理、心跳保活、遇到的问题等》
《为何基于TCP协议的移动端IM仍然需要心跳保活机制?》
《微信团队原创分享:Android版微信后台保活实战分享(进程保活篇)》
《微信团队原创分享:Android版微信后台保活实战分享(网络保活篇)》
《移动端IM实践:实现Android版微信的智能心跳机制》
《移动端IM实践:WhatsApp、Line、微信的心跳策略分析》
>> 更多同类文章 ……

[4] 有关WEB端即时通讯开发:
《新手入门贴:史上最全Web端即时通讯技术原理详解》
《Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE》
《SSE技术详解:一种全新的HTML5服务器推送事件技术》
《Comet技术详解:基于HTTP长连接的Web端实时通信技术》
《WebSocket详解(一):初步认识WebSocket技术》
《socket.io实现消息推送的一点实践及思路》
>> 更多同类文章 ……

[5] 有关IM架构设计:
《浅谈IM系统的架构设计》
《简述移动端IM开发的那些坑:架构设计、通信协议和客户端》
《一套原创分布式即时通讯(IM)系统理论架构方案》
《从零到卓越:京东客服即时通讯系统的技术架构演进历程》
《蘑菇街即时通讯/IM服务器开发之架构选择》
《腾讯QQ1.4亿在线用户的技术挑战和架构演进之路PPT》
《微信技术总监谈架构:微信之道——大道至简(演讲全文)》
《如何解读《微信技术总监谈架构:微信之道——大道至简》》
《快速裂变:见证微信强大后台架构从0到1的演进历程(一)》
《17年的实践:腾讯海量产品的技术方法论》
>> 更多同类文章 ……

[6] 有关IM安全的文章:
《即时通讯安全篇(一):正确地理解和使用Android端加密算法》
《即时通讯安全篇(二):探讨组合加密算法在IM中的应用》
《即时通讯安全篇(三):常用加解密算法与通讯安全讲解》
《即时通讯安全篇(四):实例分析Android中密钥硬编码的风险》
《传输层安全协议SSL/TLS的Java平台实现简介和Demo演示》
《理论联系实际:一套典型的IM通信协议设计详解(含安全层设计)》
《微信新一代通信安全解决方案:基于TLS1.3的MMTLS详解》
《来自阿里OpenIM:打造安全可靠即时通讯服务的技术实践分享》
>> 更多同类文章 ……

[7] 有关实时音视频开发:
《即时通讯音视频开发(一):视频编解码之理论概述》
《即时通讯音视频开发(二):视频编解码之数字视频介绍》
《即时通讯音视频开发(三):视频编解码之编码基础》
《即时通讯音视频开发(四):视频编解码之预测技术介绍》
《即时通讯音视频开发(五):认识主流视频编码技术H.264》
《即时通讯音视频开发(六):如何开始音频编解码技术的学习》
《即时通讯音视频开发(七):音频基础及编码原理入门》
《即时通讯音视频开发(八):常见的实时语音通讯编码标准》
《即时通讯音视频开发(九):实时语音通讯的回音及回音消除概述》
《即时通讯音视频开发(十):实时语音通讯的回音消除技术详解》
《即时通讯音视频开发(十一):实时语音通讯丢包补偿技术详解》
《即时通讯音视频开发(十二):多人实时音视频聊天架构探讨》
《即时通讯音视频开发(十三):实时视频编码H.264的特点与优势》
《即时通讯音视频开发(十四):实时音视频数据传输协议介绍》
《即时通讯音视频开发(十五):聊聊P2P与实时音视频的应用情况》
《即时通讯音视频开发(十六):移动端实时音视频开发的几个建议》
《即时通讯音视频开发(十七):视频编码H.264、V8的前世今生》
《简述开源实时音视频技术WebRTC的优缺点》
《良心分享:WebRTC 零基础开发者教程(中文)》
>> 更多同类文章 ……

[8] IM开发综合文章:
《移动端IM开发需要面对的技术问题》
《开发IM是自己设计协议用字节流好还是字符流好?》
《请问有人知道语音留言聊天的主流实现方式吗?》
《IM系统中如何保证消息的可靠投递(即QoS机制)》
《谈谈移动端 IM 开发中登录请求的优化》
《完全自已开发的IM该如何设计“失败重试”机制?》
《微信对网络影响的技术试验及分析(论文全文)》
《即时通讯系统的原理、技术和应用(技术论文)》
《开源IM工程“蘑菇街TeamTalk”的现状:一场有始无终的开源秀》
>> 更多同类文章 ……

[9] 开源移动端IM技术框架资料:
《开源移动端IM技术框架MobileIMSDK:快速入门》
《开源移动端IM技术框架MobileIMSDK:常见问题解答》
《开源移动端IM技术框架MobileIMSDK:压力测试报告》
《开源移动端IM技术框架MobileIMSDK:Android版Demo使用帮助》
《开源移动端IM技术框架MobileIMSDK:Java版Demo使用帮助》
《开源移动端IM技术框架MobileIMSDK:iOS版Demo使用帮助》
《开源移动端IM技术框架MobileIMSDK:Android客户端开发指南》
《开源移动端IM技术框架MobileIMSDK:Java客户端开发指南》
《开源移动端IM技术框架MobileIMSDK:iOS客户端开发指南》
《开源移动端IM技术框架MobileIMSDK:Server端开发指南》
>> 更多同类文章 ……

[10] 有关推送技术的文章:
《iOS的推送服务APNs详解:设计思路、技术原理及缺陷等》
《Android端消息推送总结:实现原理、心跳保活、遇到的问题等》
《扫盲贴:认识MQTT通信协议》
《一个基于MQTT通信协议的完整Android推送Demo》
《求教android消息推送:GCM、XMPP、MQTT三种方案的优劣》
《移动端实时消息推送技术浅析》
《扫盲贴:浅谈iOS和Android后台实时消息推送的原理和区别》
《绝对干货:基于Netty实现海量接入的推送服务技术要点》
《移动端IM实践:谷歌消息推送服务(GCM)研究(来自微信)》
《为何微信、QQ这样的IM工具不使用GCM服务推送消息?》
>> 更多同类文章 ……

[11] 更多即时通讯技术好文分类:
http://www.52im.net/forum.php?mod=collection&op=all

(原文链接:http://www.cnblogs.com/myzhibie/p/4470065.html,原文有改动)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/437008.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Qt调试技巧】Profile配置使用及一些坑

介绍 不知从哪个版本起&#xff0c;Qt Creator中的构建配置中&#xff0c;增加了一种新型配置&#xff0c;名叫“Profile”&#xff0c;如下图所示&#xff1a; 官方对Profile的描述是&#xff1a;Profile是介于Debug和Release中间的一种配置。具体是什么意思呢&#xff1f;…

【转】带你玩转Visual Studio——03.带你了解VC++各种类型的工程

上一篇文章带你玩转Visual Studio——带你新建一个工程一文中提到新建一个工程时会有很多的工程类型(图1)&#xff0c;现在将简单介绍各种类型工程的含义和主要用途。由于这里包含的工程类型太多&#xff0c;有很多本人也没有接触过&#xff0c;有些可能理解的不太对的地方还请…

如何调整金格电子章服务器印章_重磅!公安部再度认可电子签名、电子印章法律效力!...

近日&#xff0c;公安部发布《关于修改〈公安机关办理刑事案件程序规定〉的决定》&#xff0c;对《公安机关办理刑事案件程序规定》&#xff08;以下简称规定&#xff09;进行了全面修改完善&#xff0c;并将于9月1日起施行。修改后的规定共14章388条。其中&#xff0c;新增的第…

【转】带你玩转Visual Studio——04.带你高效开发

上一篇文章带你玩转Visual Studio——带你了解VC各种类型的工程一文中讲了各种类型VC工程的主要功能和用途。现在将带你一起快速开发c程序。 有过Java开发经验的人都知道Java的常用开发工具(如Eclipse、Intellij IDEA等)都有非常强大的关键字高亮、智能提示、快速追踪等的功能…

【信号与线性系统】知识点与学习攻略

知识点理解 关于正交分解可以看这个视频&#xff1a; https://www.bilibili.com/video/BV1qV411C7u6/ 记住两个完备正交函数集&#xff1a; 一个是正余弦三角函数&#xff0c;非零不同频率项乘积为0&#xff0c;非零同频率项乘积积分为T/2&#xff0c;零频率项乘积积分为T。 一…

2020-12-19

逆变&#xff08;contravariant&#xff09;与协变&#xff08;covariant&#xff09;是C#4新增的概念&#xff0c;许多书籍和博客都有讲解&#xff0c;我觉得都没有把它们讲清楚&#xff0c;搞明白了它们&#xff0c;可以更准确地去定义泛型委托和接口&#xff0c;这里我尝试画…

微软模拟飞行10厦门航空涂装_《微软飞行模拟器》多人游戏模式演示:可组队飞行...

IT之家3月29日消息 《微软飞行模拟器》(Flight Simulator)是2020年最受期待的游戏之一&#xff0c;开发商Asobo Studio现在分享了一段新的视频&#xff0c;详细介绍了《微软飞行模拟器》的多人游戏模式。《微软飞行模拟器》游戏的主模式将看到所有玩家在同一个世界中一起玩。微…

【转】UDP协议格式以及在java中的使用

UDP协议格式以及在java中的使用 UDP是面向无连接的通讯协议&#xff0c;由于通讯不需要连接&#xff0c;所以可以实现广播发送。UDP通讯时不需要接收方确认&#xff0c;属于不可靠的传输&#xff0c;可能会出现丢包现象&#xff0c;实际应用中要求程序员编程验证。 UDP适用于…

python网页填表教程_PythonSpot 中文系列教程 · 翻译完成

原文&#xff1a;PythonSpot Python Tutorials 协议&#xff1a;CC BY-NC-SA 4.0 欢迎任何人参与和完善&#xff1a;一个人可以走的很快&#xff0c;但是一群人却可以走的更远。在线阅读ApacheCN 学习资源目录PythonSpot 中文系列教程初学者 介绍Python 字符串字符串&#xff0…

【转】TCP/IP协议到底在讲什么?【乐搏TestPro】

用比喻和漫画给有需要的小伙伴解释下IP、TCP捎带题一下各种协议与HTTP协议的关系&#xff1b; 目录&#xff1a; 负责传输的IP协议 确保可靠性的TCP协议 各种协议与HTTP协议的关系 一、负责传输的IP协议 按照层次分&#xff0c;IP&#xff08;全称&#xff1a;Internet Prot…

Qt中标绘功能的实现方法对比

使用Qt开发桌面程序&#xff0c;经常会有标绘的需求&#xff0c;一般有以下几点&#xff1a; 新建&#xff1a;圆、矩形、椭圆、文字标注&#xff0c;插入图像等&#xff1b;编辑&#xff1a;指对已标绘内容的属性编辑修改功能&#xff1b;删除&#xff1a;指对已标绘内容的删…

【转】PE文件结构详解--(完整版)

&#xff08;一&#xff09;基本概念 PE&#xff08;Portable Execute&#xff09;文件是Windows下可执行文件的总称&#xff0c;常见的有DLL&#xff0c;EXE&#xff0c;OCX&#xff0c;SYS等&#xff0c;事实上&#xff0c;一个文件是否是PE文件与其扩展名无关&#xff0c;P…

【转】逆变与协变详解

逆变&#xff08;contravariant&#xff09;与协变&#xff08;covariant&#xff09;是C#4新增的概念&#xff0c;许多书籍和博客都有讲解&#xff0c;我觉得都没有把它们讲清楚&#xff0c;搞明白了它们&#xff0c;可以更准确地去定义泛型委托和接口&#xff0c;这里我尝试画…

【转】GitHub 从单机到联机:玩转 Pull Request

最近在参与一个叫 Exercism 的项目&#xff0c;这是一个由 GitHub 生态工程师 Katrina Owen 发起的编程练习社区&#xff0c;提供了超过50门语言的练习。作为用户&#xff0c;你仅需使用命令行工具即可下载和提交练习&#xff0c;提交后还可以和社区中其他学习者交流讨论。 Exe…

【转】GitHub客户端操作1--仓库相关操作github团队协作流程

1、创建仓库 点击“”&#xff0c;点击Create,然后填写Name为my&#xff0c;点击Create repository&#xff0c;即可创建一个my仓库 2、从本地仓库存放位置&#xff0c;添加test仓库到GitHub客户端 点击“”&#xff0c;点击Add,然后点击Browse&#xff0c;选择仓库存放位置&a…

【转】GitHub客户端操作2--分支操作

简单分支操作 &#xff08;1&#xff09;创建新分支&#xff1a;my分支 备注&#xff1a;新创建的分支&#xff1a;my分支里面的内容是和master分支里面的内容是完全一样的。 &#xff08;2&#xff09;删除my分支 &#xff08;3&#xff09;修改my分支【在my分支上进行项目内…

【转】GitHub客户端操作3--pull Request(拉请求)

一、参考说明 参考文章一&#xff1a;Github上提交代码(pullrequest) 网址&#xff1a; https://jingyan.baidu.com/article/358570f64dcdc2ce4724fc32.html 参考文章二&#xff1a;GitHub——Pull Request 网址&#xff1a;http://blog.csdn.net/u012325167/article/detai…

【转】GitHub上README.md教程

本文是转载文章&#xff0c;文章的来源&#xff1a;csdn博客 博主&#xff1a;果冻虾仁 文章&#xff1a; GitHub上README写法暨GFM语法解读 博文地址&#xff1a;https://blog.csdn.net/guodongxiaren/article/details/23690801 转载请保留原作者guodongxiaren的原文地址&…

【转】WPF单位真的与分辨率无关吗?

转载自http://www.cnblogs.com/helloj2ee/archive/2009/04/21/1440709.htm WPF从发布之日起&#xff0c;一直将“分辨率无关(resolution independence)”作为其亮点&#xff0c;声称使用WPF制作的用户界面在轻巧的Ultra-Mobile PC的屏幕上和在50英寸的电视机上都能很好地显示。…

【转】世上最简单的vue教程

一、需要了解的基本知识 node.js Node.js是一个Javascript运行环境(runtime)&#xff0c;发布于2009年5月&#xff0c;由Ryan Dahl开发&#xff0c;实质是对Chrome V8引擎进行了封装。Node.js对一些特殊用例进行优化&#xff0c;提供替代的API&#xff0c;使得V8在非浏览器环境…