網路基礎概論 重點整理 - HackMD

文章推薦指數: 80 %
投票人數:10人

網路基礎概論─ 重點整理## 為什麼需要通訊協定(protocol)? 請先想像一下, ... TCP / IP 是電腦網路通訊協定,分成四個層級( 應用層、傳送層、網路層、鏈結層)。

      Published LinkedwithGitHub Like2 Bookmark Subscribe #網路基礎概論─重點整理 ##為什麼需要通訊協定(protocol)? 請先想像一下,不同國家的人一起坐在一場圓桌會議上,有些人說日文、有些人說英文、有些人說中文,大家雞同鴨講,無法順利溝通。

這時候就可以使用一個語言,是大家都會的語言,這樣的語言就像是protocol。

Protocol就像是是一個格式化的標準,讓不同規格、不同語言、不同系統的系統或是平台,都能透過這樣的標準,進行資訊的流通及處理。

舉例來說,要瀏覽網站的話,要遵守網站的通訊協定,叫http(HyperTextTransferProtocol);而要傳輸檔案,則要遵循傳輸檔案用的FTP(FileTransferProtocol)。

##HTTP(超文本傳輸協定) ###概要 了解網站前,先要知道網站的資訊是如何傳送的。

Client端(ex:是瀏覽器)發送HTTPRequest(包含head跟body)請求給Server端,Server端收到後再回傳Response回應(包含head跟body)給Client端。

[詳請可看此。

](https://medium.com/@justinlee_78563/%E9%97%9C%E6%96%BCweb%E5%BE%8C%E7%AB%AF-1-%E4%BB%80%E9%BA%BC%E6%98%AFweb-server-83ee32bc7d3e) ###如何詳細看到資訊傳送的流程 1.按F12打開開發者工具。

2.點擊Network標籤,即可看到所有瀏覽器發送的所有Request跟Response(html標籤)。

3.Request跟Response都要按照既定模式才可以傳送成功。

###DNSServer(DomainNameSystem) 將DomainName網域名稱(www.google.com)翻譯成IP位址。

在terminal上可以使用`nslookup`的指令,後面加上欲查詢IP位址的網域名稱,即可查詢IP位址。

如果查詢結果是noresponsefromserver時,可以在Terminal上使用`netshwinsockreset`,再重啟電腦一次,即可順利使用`nslookup`指令。

###瀏覽器只是幫助我們協作的程式 瀏覽器是協助我們發送request,接收response的程式。

透過node.js的library─[request](https://github.com/request/request)(SimplifiedHTTPclient),也可以模擬瀏覽器發送request,步驟如下: 1.先在terminalcd到專案資料夾,並輸入`npminstallreqest`指令。

2.下載後先新增一個js檔案,並在檔案內貼上官網提供的程式碼。

這個動作是為了實作發送request。

當中的網域名稱可自由更換到自己欲實作的網頁網域。

```javascript= constrequest=require('request'); request('http://www.google.com',function(error,response,body){ console.error('error:',error);//Printtheerrorifoneoccurred console.log('statusCode:',response&&response.statusCode);//Printtheresponsestatuscodeifaresponsewasreceived console.log('body:',body);//PrinttheHTMLfortheGooglehomepage. }); ``` 3.執行`nodeindex.js>index.html`,將console.log出來的response寫入index.html內。

4.執行`index.html`(打開此檔案),即可順利看到最後結果。

###header跟body request跟response內都有包含header跟body。

header寫的是一些額外資訊,body寫的是主要內容。

###HTTP請求方法 詳細更多可以參考[MDN](https://developer.mozilla.org/zh-TW/docs/Web/HTTP/Methods)。

####get 索取並顯示資訊。

如顯示圖片或html及css。

透過devtool內可以看到requestURL。

複製此URL並另開一個分頁去執行,所看到的畫面,就是response。

而這個背後程式所做的事情,就是瀏覽器發送了一個getrequest到這個URL,並接收到了response。

####post 提交資料並請求伺服器處理。

如輸入帳號密碼。

特別注意的是,getrequest沒有body,post有。

####put 更改並取代原先資料。

假設今天原訂單是雞腿飯3,排骨飯5,put雞腿飯2,那這樣最後的訂單會是雞腿飯2,連排骨飯5都會不見。

####patch 更改指定資料。

假設今天原訂單是雞腿飯3,排骨飯5,patch雞腿飯2,那這樣最後的訂單會是雞腿飯2,排骨飯5,排骨飯5會被保留下來。

####delete 刪除資料。

####option 回傳該server可支援的溝通方式。

###HTTP狀態碼StatusCode 1.**1XX─1開頭的狀態碼:你等等(client端需要做一些處理)**。

3.**2XX─2開頭的狀態碼:成功**。

200OK就是完全順利成功 204NoContent就是成功但沒有回傳任何訊息(使用delete時)。

3.**3XX─3開頭的狀態碼:去其他地方(重新導向)**。

301MovedPermanently:就是這個網域永久的被移到其他位置,下次再度使用get時,會直接導向另一個網域。

302Found(MovedTemporarily):是暫時被移到其他位置,下次使用get時,一樣會導到此網域。

304NotModified:東西跟之前長一樣,可以從快取拿就好。

4.**4XX─4開頭的狀態碼:你慘了(client端錯誤)**。

400BadRequest:請求語法錯誤、或資源太大…等等。

401Unauthorized:未認證,可能需要登入。

403Forbidden:沒有權限。

404NotFound:找不到資源。

408RequestTimeout:請求超時。

可再隨時提交一次請求且無須修改。

5.**5XX─5開頭的狀態碼:我慘了(server端錯誤)**。

500InternalServerError:通用的伺服器出錯。

(搶票時常見) 503ServiceUnavailable:伺服器暫時無法處理。

更多請看[維基百科](https://zh.wikipedia.org/wiki/HTTP%E7%8A%B6%E6%80%81%E7%A0%81),想看有趣版可以[點此](https://noob.tw/http-status-code/)。

###實作server端 透過node.js內的library─`http`實作server端。

1.新增一個server.js檔案,並輸入以下內容。

```javascript= lethttp=require('http');//引用library:http letserver=http.createServer(handleRequest); functionhandleRequest(req,res){ console.log('requesturl:',req.url); if(req.url==='/'){ res.writeHead(200,{//更改responseheader 'info':'index' }) res.write('content');//更改responsebody res.end(); return; } if(req.url==='/redirect'){ res.writeHead(301,{//'Location':'/category'//轉址到/category 'Location':'https://google.com'//轉址到google.com }); res.end(); return; } if(req.url==='/hello'){ res.writeHead(200,{ 'info':('hello') }) res.write('hello') res.end() return; } res.write(404); res.end(); return; } server.listen(5000);//監聽5000這個port ``` 2.執行`nodeserver.js`指令(執行server) 3.server會不斷的執行直到按下Ctrl+c 驗證是否可以傳到client端: 1.打開瀏覽器的新分頁,並輸入http://localhost:5000,應該會看到畫面上出現content。

2.輸入http://localhost:5000/hello,畫面會出現hello。

3.輸入http://localhost:5000/redirect,畫面會跳轉到www.google.com。

4.隨意輸入http://localhost:5000/djioejfo,畫面會出現無法連上這個網站(404notfound)。

##TCP/IP TCP/IP是電腦網路通訊協定,分成四個層級(應用層、傳送層、網路層、鏈結層)。

更詳細可參考[鳥哥的私房菜](http://linux.vbird.org/linux_server/0110network_basic.php)。

![](https://i.imgur.com/ZSQxJCe.png) 圖片來源:鳥哥的私房菜 從這個協定當中可以看到HTTP協定〈應用層〉建立在TCP協定〈傳送層〉上,而TCP協定又建立在IP位址〈網路層〉上。

###IP地址(InternetProtocol) IP全名為InternetProtocol,中文為「網際網路協定」。

協定也有分版本,分別是IPv4(InternetProtocolversion4)跟IPv6(InternetProtocolversion6)。

IPv6可用的地址更多,解決主要IPV4不夠用的問題,兩者的地址也完全不同。

更多差異請[看這](https://www.ithome.com.tw/tech/92046)。

IP也有分成**固定IP、虛擬IP、浮動IP**。

1.**固定IP**:每一台電腦都有一個IP位置(理想狀態下),這IP位置是固定的,費用也較高。

而基本上伺服器都跟公司企業是用固定IP,這樣才能保證使用者可以連上伺服器,不會突然找不到。

2.**虛擬IP**:大公司內常常會需要因為資安因素,以連上同一個類似數據機的電腦設定虛擬IP,避免將資料帶離公司,或者是防止駭客入侵。

這些虛擬IP只有在內網才可以互相連接,對外一律都是同一個IP位置(有可能是固定IP或浮動IP)。

詳見下圖。

![](https://i.imgur.com/0hjSHuI.png) 圖片來源:Huli課程內容 這樣改變位址的數據機我們稱為NAT,底下會在更仔細的討論。

3.**浮動IP**:許多一般及家用戶都是浮動IP,IP位址會隨著每次連線而改變,好處是電信公司不需要直接給一個固定IP,也因為浮動的IP位址不易受到駭客攻擊。

想要查詢自己對外的IP位址,可以使用「myip」作為關鍵字,許多網頁都有提供這樣的服務使用。

###NAT >NAT,NetworkAddressTranslation,網路位址轉譯。

剛開始是為了解決IPv4位址不夠的的問題,而想出的一個過渡期解決辦法。

目前主要的用途是有三: 1.封包偽裝(IPmasquerade) *改變私有IP(內部IP)改變成真實IP(外部IP)再傳送到網際網路。

也就是我們前面提到的功能。

*讓其他人不知道內部到底有幾個伺服器及IP分配情形而增加網路安全性。

2.封包過濾 *可以攔截網際網路進入私有網路的封包,阻擋怪客(Cracker)的攻擊。

*因上述,NAT是最重要的防火牆成員,也是一種「封包過濾器(Packetfilter)。

3.負載平衡(LoadBalance) *通常使用在webserver,一般網頁可能同時會有很多人連線到伺服器,單一台主機(伺服器)沒有辦法負荷這麼多的連線請求,這時候就可以透過前面說的封包偽裝的特性,更改IP位址後發送到不同的主機,藉此減輕單一主機的負擔,同時增加網路安全性。

備註:其實有個東西叫做[負載平衡器](https://zh.wikipedia.org/wiki/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1)(LoadBalancer),是一個軟體程式,主要就是在負責loadbalance,詳細可參考[文章一](https://akuma1.pixnet.net/blog/post/168326978-%E5%A4%A7%E6%9E%B6%E6%A7%8B%E7%9A%84%E6%A6%82%E5%BF%B5%E8%88%87%E7%A8%8B%E5%BC%8F%E8%A8%AD%E8%A8%88%EF%BC%8D%EF%BC%8D%EF%BC%88%E4%B8%89%EF%BC%89load-balance)及[文章二](https://wiki.mbalib.com/zh-tw/%E8%B4%9F%E8%BD%BD%E5%B9%B3%E8%A1%A1) [資料來源](https://www.stockfeel.com.tw/nat-%E4%BC%BA%E6%9C%8D%E5%99%A8%E6%98%AF%E4%BB%80%E9%BA%BC%EF%BC%9F%E5%A6%82%E4%BD%95%E9%81%8B%E7%94%A8%EF%BC%9F/) ###Port連接埠(端口) 為了區分並接收同個電腦(IP位址)的不同服務,所以就有了Port。

在剛剛的實作一個server端所輸入的`server.listen(5000);`,這邊的5000就是一個port。

預設的port有HTTP(80)、HTTPS(443)、FTP(21)。

常見的測試值為3000、4000、4001。

###TCP與UDP TCP與UDP都是傳送層中的兩個協議。

大部分的網路協定都是建立在TCP上,因為TCP較為可靠、會透過「**三次握手**」確保資料送達。

而UDP重點在於速度,在日常網路應用上像是視訊或是轉播時,重點在於傳送速度而不是傳送穩定,因為漏了一兩個封包其實對使用者並不會有明顯的影響。

**何謂三次握手**? >三次握手又稱三路握手,全名為threee-wayhandshake。

簡單來說client端跟server端會通過三次的聯繫來確保資訊有確實傳達給對方。

![](https://i.imgur.com/7WVAE4q.png) 圖片來源:由原上傳者為中文維基百科的Huage.chen-Transferredfromzh.wikipediatoCommonsbyShizhaousingCommonsHelper.,CCBY-SA3.0,https://commons.wikimedia.org/w/index.php?curid=36967543 ###總結 |層級內容|層級用義|紙條故事| |--------|------|--------| |HTTP/FTP|傳輸內容|紙條內容| |TCP/UDP|傳輸方式|三次確認/講求速度| |IP|傳輸地址|寄件人和收件人| |實體層|實體傳輸|郵差| ##Server伺服器 這裡的伺服器**並非**指的是像Apache(WebServer)、FTPServer這類管理伺服器的軟體。

這裡的伺服器指的是執行上述各種伺服器管理軟體的主機,伺服器管理軟體可能還包含DNSServer、MailServer、DatabaseServer等。

通常具備較高的計算能力、能夠提供給一個或多個使用者使用的電腦/主機。

###種類 伺服器常見有三個種類: 1.虛擬空間 *只有空間而已,沒有操控權 2.虛擬主機 *一台實體主機上面有很多虛擬主機,可以視為cloud *如果共用的實體主機壞了,可以自由且無痛遷移至另一個實體主機 *需和其他虛擬主機共享CPU、記憶體等實體主機的硬體效能。

3.實體主機 *自己有一台完整的主機 *主機壞了裡面的資料也會完全損毀,難以修復 ###管理 常見管理的方式有兩種: 1.遠端連線:一般較常見在window系統,可能會使用Microsoft為Windows10所免費推出的遠端伺服器管理工具(RemoteServerAdministrationTools,RSAT),或者是其他第三方工具:像是TeamViewer、VNC。

2.SSH *全名為SecureShellProtocol,安全的殼程式協定,提供類似telnet但更安全的遠端連線。

*透過commandline介面直接連到遠端的主機下指令,通常是打`ssh+ip位址`,連線成功後可以使用`top`確認主機效能。

*最常見、普遍的管理方式。

##VPN >VirtualPrivateNetwork,虛擬私人網路。

根據維基百科,VPN是一種常用於連接中、大型企業或團體與團體間的私人網路的通訊方法。

它利用隧道協定(TunnelingProtocol)來達到傳送端認證、訊息保密與準確性等功能。

概念基本上就像是先連到一個主機,再由那個主機連線到其他地方。

常見的應用: *公司內網:先連到公司內網才能存取公司的資料。

*使用學校服務:同理,連到學校內部才能使用學校資料 *翻牆 ##API >全名為ApplicationProgrammingInterface,中文翻譯為「應用程式介面」。

簡單來說透過API就是一個交換資料的工具。

API有分很多種,這邊會提到的是基於HTTP協定下的WebAPI(HTTPAPI)。

API常見的CRUD功能分別指的是:新增(Create)、讀取(Read)、更新(Update)、刪除(Delete),有時候會聽到五項功能,多了一個列表(List)。

###如何串接API ####方法一 有個簡單提供測試是否可以串接成功的API網站─[Regres](https://reqres.in/)。

透過此網站下方jQuery內提供的URL,放入測試程式碼內,即可實測。

```javascript= constrequest=require('request'); request('https://reqres.in/api/users',function(error,response,body){ console.log(body);//PrinttheHTMLfortheGooglehomepage. }); ``` 在URL後方也可以加上欲加入的物件,像是https://reqres.in/api/users/2,即可呈現ID:2的元素。

若是想要在Terminal上直接執行`nodeindex.js2`,可以另外在檔案內加入`constprocess=require('process');`,並可以先用`console.log`測試process到底是甚麼。

在terminal上執行`nodeindex.js2`,就會發現顯示出來的結果是。

![](https://i.imgur.com/g5oHvad.jpg) 第一行顯示的結果表示,node位置。

第二行顯示的結果表示,index.js位置。

第三行顯示的結果表示,2。

process.argv[2]作為一個陣列,欲取第三個元素。

並將此放在URL後。

範例碼如下: ```javascript= constrequest=require('request'); constprocess=require('process'); request( 'https://reqres.in/api/users/'+process.argv[2], function(error,response,body){ console.log(body); } ); ``` 這時候如果在Terminal內中執行`nodeindex.js2`,即可順利顯示ID2的內容,執行`nodeindex.js3`,也可順利顯示ID3的內容。

####方法二 透過之前有提到的requestlibrary的[Github網頁](https://github.com/request/request#forms),點選forms,並使用之前所提到的[reqres](https://reqres.in/)將相關資料填入。

```javascript= constrequest=require('request'); constprocess=require('process'); request.post( { url:"https://reqres.in/api/users", form:{ name:'shelly', job:'none' } }, function(error,response,body){ console.log(body); } ); ``` 執行`nodeindex.js`也可成功寫入資料(這邊只是測試用,所以並不會真正寫入資料)。

###實測串接API 該如何實際執行API的GET、POST、PATCH、DELETE...等指令呢?可以透過之前提到的[request官方文件](https://github.com/request/request),並ctrl+F找關鍵字「request.METHOD()」,找到如何使用的方法。

以下實作DELETE跟PUT。

####DELETE 依照官網在所提供的語法(`request.delete`),以下提供範本。

```javascript= constrequest=require('request'); constprocess=require('process'); request.delete( "https://reqres.in/api/users/2", function(error,response,body){ constjson=JSON.parse(body); console.log(json); } ); ``` 執行後會發現沒跑出任何response。

這時候我們可以在第六、七行之間加上`console.log('body:',body)`,確認body內容。

執行後發現body是空的。

這時候我們可以再透過印出statuscode確認狀態。

透過`console.log(response.statusCode)`回傳的結果是204。

表示是成功的,只是沒有內容(因為已經刪除完畢)。

####PATCH 與POST運用的格式相同,範例如下: ```javascript= constrequest=require('request'); constprocess=require('process'); request.patch( { url:'https://reqres.in/api/users', form:{ Name:'Shell' } }, function(error,response,body){ console.log(body); } ); ``` ###RESTfulAPI RESTful是一種風格,該如何形容這個風格呢?就是一種語意化、更為嚴謹的描述API方式,目前也是最常見的方式。

![](https://i.imgur.com/SYoumdT.jpg) 本圖片源自Huli上課教材。

在最左邊的一欄當中是要做的事情,左二是欲使用的指令,取而代之咖啡色字體的是RESTful風格的指令,右二是非RESTful風格的寫法,右一是RESTful風格的寫法。

所以可以看到RESTful的寫法較為一致、也更好理解。

[這篇簡報](https://github.com/TritonHo/slides/blob/master/Taipei%202016-04%20talk/RESTful%20API%20Design-tw-2.1.pdf)有更仔細地談甚麼是RESTfulAPI。

##資料格式 之前我們提到的發送或是回傳的資料,都是有格式的。

這些在電腦科學中,資料格式是電腦中儲存、傳輸資料的方式。

資料格式可以簡略分成三種:純文字與自定義格式、XML、JSON。

###純文字與自定義格式 >直接透過文字跟條件式定義格式。

###XML >全名是ExtensibleMarkupLanguage,中文是可延伸性標記式語言。

XML跟HTML一樣,都是屬於MarkupLanguage標記式語言,均透過前後的標籤來包覆住內容。

這裡可參考更多[XML](https://support.office.com/zh-tw/article/xml-%E5%85%A5%E9%96%80-a87d234d-4c2e-4409-9cbc-45e4eb857d44)入門文件。

以前傳輸資料經常使用XML,現在多數人都使使用JSON。

###JSON >全名是JavaScriptObjectNotation,中文是JavaScript物件表示法。

依照維基百科,是一種輕量級的資料交換語言,該語言以易於讓人閱讀的文字為基礎,用來傳輸由屬性值或者序列性的值組成的資料物件。

雖然JSON稱之為JavaScript物件表示法,但是這個資料格式被廣泛的以函式庫的方式,用在其他語言當中。

JSON所需要的儲存空間相較XML少上許多,所以**目前JSON是最普遍被使用的資料格式。

** 在程式判讀上XML相較另一個資料格式JSON需要花費更多時間耗費資源。

更多兩個資料格式的比較,可以看[JSON與XML優缺點對比分析](https://codertw.com/%E5%89%8D%E7%AB%AF%E9%96%8B%E7%99%BC/276753/)。

####實作JSON 之前實作API時所回傳的格式,就是JSON格式。

```javascript= constrequest=require('request'); constprocess=require('process'); request( "https://reqres.in/api/users/2", function(error,response,body){ console.log(body); } ); ``` 回傳的response如以下: ```javascript= {"data":{"id":2,"email":"[email protected]","first_name":"Janet","last_name":"Weaver","avatar":"https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg"}} ``` 這個回傳的格式,就是一個JSON格式的string。

這樣的String 比較難像物件一樣直接存取物件的key。

那我們可以透過內建函式`JSON.parse()`,**將string改成物件格式。

** 將上面的`console.log(body)`改成`console.log(JSON.parse(body))`。

回傳的response則會變成以下: ```javascript= {data: {id:2, email:'[email protected]', first_name:'Janet', last_name:'Weaver', avatar: 'https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg'}} ``` 那如果是物件格式想要改成JSON格式的string,可以使用`JSON.stringify()`。

##SOAP >SOAP全名為SimpleObjectAccessProtocol,中文是簡單物件存取協定。

一種基於XML的交換資料協議規範。

目前已經很少人在使用,大多人都是使用HTTPAPI,也就是我們上方所提到且實測的。

##curl指令 curl指令操作簡單、在terminal就可以發送request(需下載)。

除了支援HTTPrequest之外,還可以上傳跟下載檔案。

以下會簡單介紹幾種常用的curl指令,更多可以看[TechBridge的介紹文章](https://blog.techbridge.cc/2019/02/01/linux-curl-command-tutorial/)及另一篇[文章](http://blog.kent-chiu.com/2013/08/14/testing-rest-with-curl-command.html),寫得非常淺顯易懂。

###基本格式 `curl[options][URL..]` ###GET `curl[URL]` *發一個GET的Request到這個網址,執行後會收到Response。

*可以組合其他指令,像是使用`curl[URL]>index.html`。

就下載此response到index.html裡。

###取得response的header 1.`curl-I[URL]` 2.`curl--head[URL]` 這邊有一篇[文章](https://www.eebreakdown.com/2016/10/curl-http.html)非常簡單的說明了如何使用curl做http的測試。

##其他常用的Commandline指令 ###Ping `ping[Url]` 測試後方放入的網址是否可順利連結上。

###telnet `telnet[URL][Port]` 查詢是否可以連接到指定的port。

剛開始無法使用,參考了[這篇文章](https://www.namecheap.com/support/knowledgebase/article.aspx/9667/2194/what-are-traceroute-ping-telnet-and-nslookup-commands#telnet),解決了第一步無法使用。

經由telnet連到IP位址的port後,可以輸入「get/」就會取得GETrequest的資料。

其它指令也是可以直接操作。

補充現狀:剛先透過`nslookup`查詢google.com的IP位址,再透過`telnet`查詢port。

但目前還是似乎無法使用`telnet`的指令,可使用的指令是`telnetptt.cc`。

##實際串接TWITCHAPI所遇到的問題 基本上按照串接TWITCHAPI的[教學文件](https://dev.twitch.tv/docs/api/)即可,但我還是遇到非常多的問題。

這邊紀錄幾個非常耗費我耐心與腦力的問題,避免之後再犯: ![](https://i.imgur.com/TQSIv1n.png) 1.STEP1:註冊完Twitch帳戶後在這邊註冊應用程式,重新導向網址後還需要加上port。

2.STEP2:在terminal輸入文件上的samplecode時,要注意的地方有很多。

*`curl:(6)Couldnotresolvehost:`和`curl:(1)Protocol"'https"notsupportedordisabledinlibcurl`的問題解法:裡面的單引號('')全數都要換成雙引號("")。

*文件內samplecode的斜槓是讓你換行,但cmder無法同時執行兩行,需要手動把/刪除。

*Client-ID冒號後不可以有空格。

參考資料:[單引號換雙引號](https://stackoverflow.com/questions/6884669/curl-1-protocol-https-not-supported-or-disabled-in-libcurl) ##實做API 可參考保哥的[影片](https://www.youtube.com/watch?v=uFKa4xrc42c)。

######tags:`HTTPRequest`、`API` 2 × Signin Email Password Forgotpassword or Byclickingbelow,youagreetoourtermsofservice. SigninviaFacebook SigninviaTwitter SigninviaGitHub SigninviaDropbox SigninviaGoogle NewtoHackMD?Signup



請為這篇文章評分?