[TOC]
## http是tcp的超集
當瀏覽器請求一個url資源的時候,先和目標服務器建立tcp長連接,然后再發送http請求。(這意味著tcp鏈接建立完成之前,http請求并沒有發送)

可以看到,這里connection先于request觸發
### 若http服務器沒有res.end(),即不會斷開連接

#### end先于close

### Q
#### http只是基于tcp的包裝?還是不同于tcp的另一個鏈接請求?
#### request是第一次發數據的時候才觸發嗎?
答:只要客戶端向服務器發送消息,每次都會觸發request事件
#### 發消息就等于客戶端鏈接嗎?
不等于,先建立鏈接才會發送http請求
## 利用curl發送http請求
下圖中“相應信息”應為“響應信息”
**注意**:-X的x為大寫,post也必須為大寫

### 請求報文
請求行 method url protocol
請求頭
空白行
請求體


### 響應報文
響應行 protocol statusCode statusDesc
響應頭
空白行
響應體



## 創建一個http服務器
```
let http = require('http');
let server = http.createServer(function(req,res){
}).listen(8080,function(){
console.log('server is running on the localhost:8080');
});
```
### req
req代表客戶端的一個請求。
server服務器把客戶端的請求進行解析,然后放在req對象上。
#### 通過req.x的方式獲取請求行和請求頭

#### req對象中拿不到hash

#### url.parse(req.url) 獲取 url對象
```
import url = require('url'); //url為nodeJS中內置的模塊,但需要引用
```

##### req.url和url對象的比較
其中`path`為路徑,`pathname`為path去掉`query`的部分
path即是 url從域名后面‘/’及其以后的部分

##### url對象中的query,以及其他

#### 從req中獲取請求體
我們不能直接通過req.data的形式拿到請求數據,但!
因為req是一個可讀流,可以通過監聽"data"事件來獲取請求體數據
**注意**:默認拿到的數據為buffer(一段16進制的類數組數據),需要toString

### res
res代表響應,如果希望向客戶端回應消息,需要通過res
#### 設置響應行和響應頭
statusCode:設置了Code會自動生成對應的描述
sendDate:設置是否在響應中顯示響應開始發送的時間
setHeader:設置響應頭
removeHeader:移除響應頭
getHeader:獲取響應頭

#### writeHead,可以將狀態碼和響應頭一起寫了
headersSent:響應頭是否已經發送

這個api存在的意義?
當調用write時響應頭就已經發送出去了
為什么調用write就發送了呢? 客戶端這時就開始接收數據了,需要知道接收的數據長撒樣
這里需要注意的是
而這時可能服務器還準備傳點什么給客戶端,還沒有res.end鏈接還沒有掛斷,

**注意**:
1. 如果是調用write而不是直接調用end,這里會分塊傳輸 見上圖【Transfer-Encoding】
2. 如果響應時沒有end,也不會在響應頭中出現【Content-Length】這個屬性
3. 這里分塊傳輸的時候字節數比應該的多,是因為:
分塊編碼相當簡單,在頭部加入 Transfer-Encoding: chunked 之后,就代表這個報文采用了分塊編碼。這時,報文中的實體需要改為用一系列分塊來傳輸。每個分塊包含十六進制的長度值和數據,長度值獨占一行,長度不包括它結尾的 CRLF(\r\n),也不包括分塊數據結尾的 CRLF。最后一個分塊長度值必須為 0,對應的分塊數據沒有內容,表示實體結束。
相關文章: https://www.cnblogs.com/simonbaker/p/5593177.html
### 創建http服務器的第二種形式
```
let server = http.createServer();
server.on('connection',function(socket){
});
server.on('request',function(req,res){
});
server.listen(8080,function(){
console.log('server started at http://localhost:8080')
});
```