# Web Server軟體 V.S. NodeJS ※本篇內容僅用以方便我自己記憶用,不一定符合業界習慣且無法保證100%正確。 ## 本篇名詞解釋 ### Web Server軟體 市面上常見的,用以開啟網頁伺服器連線服務的軟體,如[Apache HTTP Server](https://zh.wikipedia.org/zh-tw/Apache_HTTP_Server)、[Nginx](https://zh.wikipedia.org/zh-tw/Nginx)、[微軟IIS](https://zh.wikipedia.org/zh-tw/%E7%B6%B2%E9%9A%9B%E7%B6%B2%E8%B7%AF%E8%B3%87%E8%A8%8A%E6%9C%8D%E5%8B%99)。 ### HTTP Server 定義大致上等同網頁伺服器(Web Server)。 接收來自HTTP protocol(且通常是通過80 port或443 port)的流量並進行處理、給予回應的伺服器。80 port為HTTP protocol常用的連接埠,443則為HTTPS(含確認安全憑證相關程序,為目前主流的網頁通訊協定)的常用連接埠。 ### Node.js JavaScript的框架(Framework),用來撰寫網路服務相關的功能,模組化、入門難度低,且**可以取代其他Web Server軟體,用來打開HTTP Server**。 <br> ## 實作 & 區別 以下皆以我本次實作經驗為例,作業系統為Ubuntu 22.04.1 LTS,使用Apache2來當HTTP Server,並讓Nodejs的WebSocket模組接管3000 port。 ### Apache **在預設config下,Apache會監聽80 port的流量,建立一個HTTP Server**。啟動Apache之後,一般使用者即可透過在瀏覽器輸入http://{IP-address}:80來存取你的網頁 (或http://{domain-name}:80,如果你有綁定域名的話)。網址後面的:80表示使用者透過80 port連線,由於80和443是最常用的HTTP port number,key網址時通常可以直接省略。 網頁要顯示的內容預設是編寫在/var/www/html底下的index.html中。 申請憑證且設定好SSL相關config後,可透過指令開啟https連線功能 (通常也就是443 port的對外連線,記得也要allow linux防火牆的443流量)。 (相關教學:[Apache 安裝 HTTPS 教學](https://medium.com/feveral%E7%9A%84%E7%A8%8B%E5%BC%8F%E7%AD%86%E8%A8%98/apache-%E5%AE%89%E8%A3%9D-https-%E6%95%99%E5%AD%B8-dd022e2be7b4)) ``` # 撰寫SSL相關的config sudo vim /etc/apache2/sites-enabled/ssl.conf # 啟用剛剛寫好的ssl.conf sudo a2enmod ssl # 重開Apache sudo service apache2 restart # 允許443 port通過防火牆 sudo ufw allow 443 ``` 另外,透過編輯config檔案,可設定proxy,依照不同情況把client的request重新導向到指定的port做處理,或者做自動轉址(如:把 http:// 自動轉址到 https:// ,半強制使用者透過https連線,避免沒有經過SSL憑證驗證的流量) (相關範例:[如何設定WebSocket轉導與分流](https://www.tpisoftware.com/tpu/articleDetails/947) 、 [How to automatically redirect HTTP to HTTPS on Apache servers?](https://stackoverflow.com/questions/16200501/how-to-automatically-redirect-http-to-https-on-apache-servers)) 如果需要開啟其他port,同樣可透過編輯config檔案來達成。 ###### > /etc/apache2/sites-enabled/000-default.conf (VirtualHost後面的*:80為port number)  ###### > 開啟80與443 port之後,透過netstat指令確認這些port的監聽狀況  ### Node.js 同樣可用來開啟server,監聽的port依照程式碼編寫內容而定,也可以一次開啟並監聽數個port。 如果監聽80 port或者443 port,大致上便是取代了Apache的功能、建立一般的HTTP Server。 以下範例程式是以nodejs的https套件來開啟HTTP server,且這裡指定的port number是3000 port而不是443 port,因為待會還有特殊用途。 (相關教學:[Day7 - Node.js 內建的 Web Server 介紹及使用](https://ithelp.ithome.com.tw/articles/10185302)) ```javascript= //import相關套件 const fs = require('fs') const https = require('https') const SocketServer = require('ws').Server const PORT = 3000 //指定 port const options = { // SSL憑證相關檔案路徑 key: fs.readFileSync('/privkey.pem'), cert: fs.readFileSync('/fullchain.pem'), } //建立server const server = https.createServer(options); server.listen(PORT, '0.0.0.0', () => { console.log(`Listening on ${PORT}`); }); ``` 到這邊一般使用者即可透過輸入https://{domain-name}:3000來連上你的網頁,但因為網頁內容是空白的,瀏覽器可能會回傳EMPTY RESPONSE錯誤訊息來告訴你它沒有東西可顯示。 ###### > 透過netstat指令,可以看到在執行node之後,3000 port已經被監聽了。  承上述程式碼,接下來我將server交給ws套件,它將開啟WebSocket(另一種通訊協定)的相關服務。 ```javascript= //將 express 交給 SocketServer 開啟 WebSocket 的服務 const wss = new SocketServer({ server }); ``` 從這裡開始,一般使用者就無法再透過https://{domain-name}:3000連上你的網頁,因為3000 port目前已經被WebSocekt server監聽,得透過**wss**://{domain-name}:3000來連線 (但並不是直接輸入在瀏覽器的網址列,必須透過WebSocket協定來連線,這部份有一些線上測試工具可以用) ※因為前面使用的是**https**連線,所以WebSocket會強制規定Client端只能用同樣有通過SSL驗證程序的**wss://** (WebSockets over SSL/TLS)來連線,否則會報錯。如果前面用的是不需要安全憑證的**http**,則可以用**ws://** 開頭的網址進行連線。 WebSocket協定可以做到讓使用者與伺服器即時互動,甚至再透過伺服器broadcast來達到使用者與使用者即時互動的效果。以這支程式為例,呈現的就是簡易的即時聊天室功能。 (參考範例:[[WebSocket] 實作一個簡單的聊天室 (+ Node.js)](https://eudora.cc/posts/220105/))  ```javascript= //當有 client 連線成功時 wss.on('connection', ws => { ws.send("This website is for test purpose, please do not leave any personal information here."); console.log('Client connected') // 當收到client消息時 ws.on('message', data => { // 收回來是 Buffer 格式、需轉成字串 data = data.toString() console.log(data) // 可在 terminal 看收到的訊息 /// 發送消息給client ws.send(data) /// 發送給所有client: let clients = wss.clients //取得所有連接中的 client clients.forEach(client => { client.send(data) // 發送至每個 client }) }) // 當連線關閉 ws.on('close', () => { console.log('Close connected') }) }) ``` ### 流程圖 
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up