from:
socket是套接字肉渴,多指傳輸層網(wǎng)絡(luò)接口。
Socket和SocketServer是基于套接字的服務(wù)端和客戶端實現(xiàn)
webSocket僚匆,是一個應(yīng)用層協(xié)議微渠,說的是,目前瀏覽器實現(xiàn)的一套通信協(xié)議咧擂,用來解決之前HTTP逞盆,請求響應(yīng)模型不合適的場合。
Socket和SocketServer是服務(wù)端和客戶端的區(qū)別
1. 服務(wù)器端程序設(shè)計
在服務(wù)器端松申,利用ServerSocket類的構(gòu)造函數(shù)ServerSocket(int port)創(chuàng)建一個ServerSocket類的對象云芦,port參數(shù)傳遞端口,這個端口就是服務(wù)器監(jiān)聽連接請求的端口贸桶,如果在這時出現(xiàn)錯誤將拋出IOException異常對象舅逸,否則將創(chuàng)建ServerSocket對象并開始準(zhǔn)備接收連接請求。
服務(wù)程序從調(diào)用ServerSocket的accept()方法開始皇筛,直到連接建立琉历。在建立連接后,accept()返回一個最近創(chuàng)建的Socket對象,該Socket對象綁定了客戶程序的IP地址或端口號旗笔。
2.客戶端程序設(shè)計
當(dāng)客戶程序需要與服務(wù)器程序通信時彪置,需在客戶機(jī)創(chuàng)建一個Socket對象。Socket類有構(gòu)造函數(shù)Socket(InetAddress addr蝇恶,int port)和Socket(String host拳魁,intport),兩個構(gòu)造函數(shù)都創(chuàng)建了一個基于Socket的連接服務(wù)器端流套接字的流套接字撮弧。對于第一個InetAd-dress子類對象通過addr參數(shù)獲得服務(wù)器主機(jī)的IP地址潘懊,對于第二個函數(shù)host參數(shù)包被分配到InetAddress對象中,如果沒有IP地址與host參數(shù)相一致想虎,那么將拋出UnknownHostException異常對象卦尊。兩個函數(shù)都通過參數(shù)port獲得服務(wù)器的端口號。假設(shè)已經(jīng)建立連接了舌厨,網(wǎng)絡(luò)API將在客戶端基于Socket的流套接字中捆綁客戶程序的IP地址和任意一個端口號岂却,否則兩個函數(shù)都會拋出一個IOException對象。
如果創(chuàng)建了一個Socket對象裙椭,那么它可通過get-InputStream()方法從服務(wù)程序獲得輸入流讀傳送來的信息躏哩,也可通過調(diào)用getOutputStream()方法獲得輸出流來發(fā)送消息。在讀寫活動完成之后揉燃,客戶程序調(diào)用close()方法關(guān)閉流和流套接字扫尺。
WebSocket是HTML5后提出的實現(xiàn)長連接的方式
一、WebSocket是HTML5出的東西(協(xié)議)炊汤,也就是說HTTP協(xié)議沒有變化正驻,或者說沒關(guān)系,但HTTP是不支持持久連接的(長連接抢腐,循環(huán)連接的不算)
首先HTTP有1.1和1.0之說姑曙,也就是所謂的keep-alive,把多個HTTP請求合并為一個迈倍,但是Websocket其實是一個新協(xié)議伤靠,跟HTTP協(xié)議基本沒有關(guān)系,只是為了兼容現(xiàn)有瀏覽器的握手規(guī)范而已啼染,也就是說它是HTTP協(xié)議上的一種補(bǔ)充可以通過這樣一張圖理解
有交集宴合,但是并不是全部。
另外Html5是指的一系列新的API迹鹅,或者說新規(guī)范卦洽,新技術(shù)。Http協(xié)議本身只有1.0和1.1斜棚,而且跟Html本身沒有直接關(guān)系逐样。。
通俗來說,你可以用HTTP協(xié)議傳輸非Html數(shù)據(jù)脂新,就是這樣=挪捕。=
再簡單來說,層級不一樣争便。
二级零、Websocket是什么樣的協(xié)議,具體有什么優(yōu)點
首先滞乙,Websocket是一個持久化的協(xié)議奏纪,相對于HTTP這種非持久的協(xié)議來說。
簡單的舉個例子吧斩启,用目前應(yīng)用比較廣泛的PHP生命周期來解釋序调。
1) HTTP的生命周期通過Request來界定,也就是一個Request 一個Response兔簇,那么在HTTP1.0中发绢,這次HTTP請求就結(jié)束了。
在HTTP1.1中進(jìn)行了改進(jìn)垄琐,使得有一個keep-alive边酒,也就是說,在一個HTTP連接中狸窘,可以發(fā)送多個Request墩朦,接收多個Response。
但是請記住 Request = Response 翻擒, 在HTTP中永遠(yuǎn)是這樣氓涣,也就是說一個request只能有一個response。而且這個response也是被動的陋气,不能主動發(fā)起春哨。
教練,你BB了這么多恩伺,跟Websocket有什么關(guān)系呢?
_(:з」∠)_好吧椰拒,我正準(zhǔn)備說Websocket呢晶渠。。
首先Websocket是基于HTTP協(xié)議的燃观,或者說借用了HTTP的協(xié)議來完成一部分握手褒脯。
在握手階段是一樣的
-------以下涉及專業(yè)技術(shù)內(nèi)容,不想看的可以跳過lol:缆毁,或者只看加黑內(nèi)容--------
首先我們來看個典型的Websocket握手(借用Wikipedia的番川。。)
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
熟悉HTTP的童鞋可能發(fā)現(xiàn)了,這段類似HTTP協(xié)議的握手請求中颁督,多了幾個東西践啄。
我會順便講解下作用。
Upgrade: websocket
Connection: Upgrade
這個就是Websocket的核心了沉御,告訴Apache屿讽、Nginx等服務(wù)器:注意啦,窩發(fā)起的是Websocket協(xié)議吠裆,快點幫我找到對應(yīng)的助理處理~不是那個老土的HTTP伐谈。
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
首先,Sec-WebSocket-Key 是一個Base64 encode的值试疙,這個是瀏覽器隨機(jī)生成的诵棵,告訴服務(wù)器:泥煤,不要忽悠窩祝旷,我要驗證尼是不是真的是Websocket助理履澳。
然后,Sec_WebSocket-Protocol 是一個用戶定義的字符串缓屠,用來區(qū)分同URL下奇昙,不同的服務(wù)所需要的協(xié)議。簡單理解:今晚我要服務(wù)A敌完,別搞錯啦~
最后储耐,Sec-WebSocket-Version 是告訴服務(wù)器所使用的Websocket Draft(協(xié)議版本),在最初的時候滨溉,Websocket協(xié)議還在 Draft 階段什湘,各種奇奇怪怪的協(xié)議都有,而且還有很多期奇奇怪怪不同的東西晦攒,什么Firefox和Chrome用的不是一個版本之類的闽撤,當(dāng)初Websocket協(xié)議太多可是一個大難題。脯颜。不過現(xiàn)在還好哟旗,已經(jīng)定下來啦~大家都使用的一個東西~ 脫水:服務(wù)員,我要的是13歲的噢→_→
然后服務(wù)器會返回下列東西栋操,表示已經(jīng)接受到請求闸餐, 成功建立Websocket啦!
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
這里開始就是HTTP最后負(fù)責(zé)的區(qū)域了矾芙,告訴客戶舍沙,我已經(jīng)成功切換協(xié)議啦~
Upgrade: websocket
Connection: Upgrade
依然是固定的,告訴客戶端即將升級的是Websocket協(xié)議剔宪,而不是mozillasocket拂铡,lurnarsocket或者shitsocket壹无。
然后,Sec-WebSocket-Accept 這個則是經(jīng)過服務(wù)器確認(rèn)感帅,并且加密過后的 Sec-WebSocket-Key斗锭。服務(wù)器:好啦好啦,知道啦留瞳,給你看我的ID CARD來證明行了吧拒迅。。
后面的她倘,Sec-WebSocket-Protocol 則是表示最終使用的協(xié)議璧微。
至此,HTTP已經(jīng)完成它所有工作了硬梁,接下來就是完全按照Websocket協(xié)議進(jìn)行了前硫。
具體的協(xié)議就不在這闡述了。
------------------技術(shù)解析部分完畢------------------
你TMD又BBB了這么久荧止,那到底Websocket有什么鬼用屹电,http long poll,或者ajax輪詢不都可以實現(xiàn)實時信息傳遞么跃巡。
好好好危号,年輕人,那我們來講一講Websocket有什么用素邪。
來給你吃點胡(蘇)蘿(丹)卜(紅)
三外莲、Websocket的作用
在講Websocket之前,我就順帶著講下 long poll 和 ajax輪詢 的原理兔朦。
首先是 ajax輪詢 偷线,ajax輪詢 的原理非常簡單,讓瀏覽器隔個幾秒就發(fā)送一次請求沽甥,詢問服務(wù)器是否有新信息声邦。
場景再現(xiàn):
客戶端:啦啦啦,有沒有新信息(Request)
服務(wù)端:沒有(Response)
客戶端:啦啦啦摆舟,有沒有新信息(Request)
服務(wù)端:沒有亥曹。。(Response)
客戶端:啦啦啦恨诱,有沒有新信息(Request)
服務(wù)端:你好煩啊媳瞪,沒有啊。胡野。(Response)
客戶端:啦啦啦,有沒有新消息(Request)
服務(wù)端:好啦好啦痕鳍,有啦給你硫豆。(Response)
客戶端:啦啦啦龙巨,有沒有新消息(Request)
服務(wù)端:。熊响。旨别。。汗茄。沒秸弛。。洪碳。递览。沒。瞳腌。绞铃。沒有(Response) ---- loop
long poll
long poll 其實原理跟 ajax輪詢 差不多,都是采用輪詢的方式嫂侍,不過采取的是阻塞模型(一直打電話儿捧,沒收到就不掛電話),也就是說挑宠,客戶端發(fā)起連接后菲盾,如果沒消息,就一直不返回Response給客戶端各淀。直到有消息才返回懒鉴,返回完之后,客戶端再次建立連接揪阿,周而復(fù)始疗我。
場景再現(xiàn)
客戶端:啦啦啦,有沒有新信息南捂,沒有的話就等有了才返回給我吧(Request)
服務(wù)端:額吴裤。。 等待到有消息的時候溺健。麦牺。來 給你(Response)
客戶端:啦啦啦,有沒有新信息鞭缭,沒有的話就等有了才返回給我吧(Request) -loop
從上面可以看出其實這兩種方式剖膳,都是在不斷地建立HTTP連接,然后等待服務(wù)端處理岭辣,可以體現(xiàn)HTTP協(xié)議的另外一個特點吱晒,被動性。
何為被動性呢沦童,其實就是仑濒,服務(wù)端不能主動聯(lián)系客戶端叹话,只能有客戶端發(fā)起。
簡單地說就是墩瞳,服務(wù)器是一個很懶的冰箱(這是個梗)(不會驼壶、不能主動發(fā)起連接),但是上司有命令喉酌,如果有客戶來热凹,不管多么累都要好好接待。
說完這個泪电,我們再來說一說上面的缺陷(原諒我廢話這么多吧OAQ)
從上面很容易看出來般妙,不管怎么樣,上面這兩種都是非常消耗資源的歪架。
ajax輪詢 需要服務(wù)器有很快的處理速度和資源股冗。(速度)
long poll 需要有很高的并發(fā),也就是說同時接待客戶的能力和蚪。(場地大兄棺础)
所以ajax輪詢 和long poll 都有可能發(fā)生這種情況。
客戶端:啦啦啦啦攒霹,有新信息么怯疤?
服務(wù)端:月線正忙,請稍后再試(503 Server Unavailable)
客戶端:催束。集峦。。抠刺。好吧塔淤,啦啦啦,有新信息么速妖?
服務(wù)端:月線正忙高蜂,請稍后再試(503 Server Unavailable)
客戶端:
然后服務(wù)端在一旁忙的要死:冰箱,我要更多的冰箱罕容!更多备恤。。更多锦秒。露泊。(我錯了。旅择。這又是梗惭笑。。)
--------------------------
言歸正傳生真,我們來說Websocket吧
通過上面這個例子沉噩,我們可以看出铺敌,這兩種方式都不是最好的方式,需要很多資源屁擅。
一種需要更快的速度,一種需要更多的'電話'产弹。這兩種都會導(dǎo)致'電話'的需求越來越高派歌。
哦對了,忘記說了HTTP還是一個狀態(tài)協(xié)議痰哨。
通俗的說就是胶果,服務(wù)器因為每天要接待太多客戶了,是個健忘鬼斤斧,你一掛電話早抠,他就把你的東西全忘光了,把你的東西全丟掉了撬讽。你第二次還得再告訴服務(wù)器一遍蕊连。
所以在這種情況下出現(xiàn)了,Websocket出現(xiàn)了游昼。
他解決了HTTP的這幾個難題甘苍。
首先,被動性烘豌,當(dāng)服務(wù)器完成協(xié)議升級后(HTTP->Websocket)载庭,服務(wù)端就可以主動推送信息給客戶端啦。
所以上面的情景可以做如下修改廊佩。
客戶端:啦啦啦囚聚,我要建立Websocket協(xié)議,需要的服務(wù):chat标锄,Websocket協(xié)議版本:17(HTTP Request)
服務(wù)端:ok顽铸,確認(rèn),已升級為Websocket協(xié)議(HTTP Protocols Switched)
客戶端:麻煩你有信息的時候推送給我噢鸯绿。跋破。
服務(wù)端:ok,有的時候會告訴你的瓶蝴。
服務(wù)端:balabalabalabala
服務(wù)端:balabalabalabala
服務(wù)端:哈哈哈哈哈啊哈哈哈哈
服務(wù)端:笑死我了哈哈哈哈哈哈哈
就變成了這樣毒返,只需要經(jīng)過一次HTTP請求,就可以做到源源不斷的信息傳送了舷手。(在程序設(shè)計中拧簸,這種設(shè)計叫做回調(diào),即:你有信息了再來通知我男窟,而不是我傻乎乎的每次跑來問你)
這樣的協(xié)議解決了上面同步有延遲盆赤,而且還非常消耗資源的這種情況贾富。
那么為什么他會解決服務(wù)器上消耗資源的問題呢?
其實我們所用的程序是要經(jīng)過兩層代理的牺六,即HTTP協(xié)議在Nginx等服務(wù)器的解析下颤枪,然后再傳送給相應(yīng)的Handler(PHP等)來處理。
簡單地說淑际,我們有一個非澄犯伲快速的接線員(Nginx),他負(fù)責(zé)把問題轉(zhuǎn)交給相應(yīng)的客服(Handler)春缕。
本身接線員基本上速度是足夠的盗胀,但是每次都卡在客服(Handler)了,老有客服處理速度太慢锄贼。票灰,導(dǎo)致客服不夠。
Websocket就解決了這樣一個難題宅荤,建立后屑迂,可以直接跟接線員建立持久連接,有信息的時候客服想辦法通知接線員冯键,然后接線員在統(tǒng)一轉(zhuǎn)交給客戶屈糊。
這樣就可以解決客服處理速度過慢的問題了。
同時琼了,在傳統(tǒng)的方式上逻锐,要不斷的建立,關(guān)閉HTTP協(xié)議雕薪,由于HTTP是非狀態(tài)性的昧诱,每次都要重新傳輸identity info(鑒別信息),來告訴服務(wù)端你是誰所袁。
雖然接線員很快速盏档,但是每次都要聽這么一堆,效率也會有所下降的燥爷,同時還得不斷把這些信息轉(zhuǎn)交給客服蜈亩,不但浪費客服的處理時間,而且還會在網(wǎng)路傳輸中消耗過多的流量/時間前翎。
但是Websocket只需要一次HTTP握手稚配,所以說整個通訊過程是建立在一次連接/狀態(tài)中,也就避免了HTTP的非狀態(tài)性港华,服務(wù)端會一直知道你的信息道川,直到你關(guān)閉請求,這樣就解決了接線員要反復(fù)解析HTTP協(xié)議,還要查看identity info的信息冒萄。
同時由客戶主動詢問臊岸,轉(zhuǎn)換為服務(wù)器(推送)有信息的時候就發(fā)送(當(dāng)然客戶端還是等主動發(fā)送信息過來的。尊流。)帅戒,沒有信息的時候就交給接線員(Nginx),不需要占用本身速度就慢的客服(Handler)了