前一段時間通過wireshark抓包,定位了乙個客戶端和伺服器之間資料傳輸的問題。最近就抽空看了看《tcp/ip詳解 卷1》中關於tcp的部分,書中用了很多例子展示了tcp/ip協議中的一些基本概念。
所以,也準備自己動手,通過一些簡單的實驗來進一步了解一下tcp中的一些基本概念。
在開始進行實驗之前,首先看看實驗環境的搭建:
一台虛擬機器:如果客戶端和服務端都在本機,那麼資料通訊是不經過網絡卡的,所以wireshark就抓不到任何資料報。方便的辦法就是本機安裝乙個虛擬機器,通過本機和虛擬機器通訊進行實驗。我使用的是virtualbox+winxp.
獲取網路裝置
接收、解析資料報
建立、傳送資料報
在建立好實驗環境之後,還需要進行一些簡單的配置,保證宿主機和虛擬機器之間的網路是暢通的。
將虛擬機器網路設定為"host-only adapter"模式。
虛擬機器網路設定好之後,就可以配置本機和虛擬機器ip位址了,然後保證宿主機可以ping通虛擬機器。
通過上面的步驟,簡單的實驗環境就建立完成了,下面就要來實現客戶端和服務端了,試試實驗環境是否能夠正常工作。
首先,將虛擬機器(192.168.56.102)作為服務端,執行下面一段**建立乙個簡單的socket server,服務端繫結192.168.56.102:8081:
import客戶端的實現在本機(192.168.56.101),使用一段基於pcap.net的**向伺服器傳送乙個[syn]包(tcp連線建立需要進行三次握手,[syn]包就是第乙個握手包),來請求建立tcp連線。sysfrom socket import *host = "
192.168.56.102
"port = 8081bufsiz = 1024addr =(host, port)
server =socket(af_inet, sock_stream)
"socket created
"try
: server.bind(addr)
except
error, msg:
'bind failed. error code :
' + str(msg[0]) + '
message
' + msg[1]
sys.exit()
server.listen(10)
'socket now listening
'while
true:
conn, addr =server.accept()
try:
data = conn.recv(100)
ifdata:
data
except
exception, e:
e conn.close()
在客戶端**中,通過pcap.net實現了兩個工具函式,乙個用來獲取本機網絡卡裝置列表,乙個用在構造不同型別的tpc包。
獲取本機網絡卡裝置列表**:
public另一段重要的**就是構造tcp包的**,根據osi七層模型,下面**中分別建立了鏈路層、網路層和傳輸層的部分,然後生成乙個資料報:static
packetdevice getnicdevice()
//print the device list
for (int i = 0; i != alldevices.count; ++i)
int deviceindex = 0
;
do }
while (deviceindex == 0
);
return alldevices[deviceindex - 1
];}
public主程式中,首先配置了客戶端和伺服器的埠、ip/mac位址資訊,然後通過前面兩個工具函式構造乙個tcp連線建立請求包([syn]包),並通過"virtualbox host-only network"網絡卡傳送給服務端。static packet buildtcppacket(endpointinfo endpointinfo, tcpcontrolbits tcpcontrolbits, listtcpoptionlist = null);
ipv4layer ipv4layer =
newipv4layer
;tcplayer tcplayer =
newtcplayer
;packetbuilder builder = new
packetbuilder(ethernetlayer, ipv4layer, tcplayer);
return
builder.build(datetime.now);
}
static**完成了,下面看看執行效果,為了直觀的看到資料報的傳輸,這是就可以開啟wireshark了。void main(string
args)
communicator.sendpacket(utils.buildtcppacket(endpointinfo, tcpcontrolbits.synchronize,
null
)); packethandler(communicator, endpointinfo);
}console.writeline(
"press enter to quit!");
console.readline();
}private
static
void
packethandler(packetcommunicator communicator, endpointinfo endpointinfo)
} while (true
);}
為了避免抓到不相關的資料報,可以設定wireshark中的filter,然後開始抓取。
下面執行**,並選擇正確的網絡卡。通過console和wireshark的輸出可以看到,我們成功的生產了乙個[syn]包併發送到了伺服器。
根據tcp連線建立過程可以知道,客戶端傳送[syn]包後,期待從伺服器得到乙個[syn, ack]包。
到這裡,說明前面搭建的環境,以及客戶端和服務端的**都是可以正常工作的了。
從上面的結果中看到,客戶端在收到[syn, ack]包之後,傳送了乙個[rst]包重置這條tcp連線。
仔細檢視了**發現,客戶端的**中並沒有傳送[rst]包。那麼這個[rst]包是**來的呢?
作業系統中有協議棧的概念,所以來自應用層的資料,都會一層層的經過作業系統協議棧處理,然後通過網絡卡傳送出去。
當客戶端網絡卡收到[syn, ack]包後,這個包會被我們的pcap.net程式捕獲,也會被傳送給客戶端作業系統。由於通過pcap.net構造的[syn]包是沒有經過作業系統協議棧的,所以作業系統會認為[syn, ack]包是乙個無效tcp包,並通過[rst]包重置tcp連線。
到這裡,多餘[rst]包就可以解釋了。
為了避免作業系統協議棧對pcap.net程式的影響,通過ip安全策略(通過run->"secpol.msc"開啟設定)的設定,可以避免作業系統從本機(192.168.56.101)向虛擬機器(192.168.56.102)傳送資料報。
設定完成後,再次執行程式,這是程式就正常了。
由於客戶端沒有傳送[ack]包來確認來自服務端的[syn, ack]包,根據tcp工作原理,服務端會進行重傳。
本文中介紹了tcp實驗環境的搭建,通過pcap.net建立了乙個客戶端,可以構造不同型別的tcp資料報,並通過特定網絡卡向伺服器傳送。
後面繼續基於這個環境來看看tcp的一些基本概念,tcp連線、狀態變遷等等。
動手學習TCP 環境搭建
前一段時間通過wireshark抓包,定位了乙個客戶端和伺服器之間資料傳輸的問題。最近就抽空看了看 tcp ip詳解 卷1 中關於tcp的部分,書中用了很多例子展示了tcp ip協議中的一些基本概念。所以,也準備自己動手,通過一些簡單的實驗來進一步了解一下tcp中的一些基本概念。在開始進行實驗之前,...
《動手學深度學習》 環境安裝
首先需要配置清華映象 pip config set global.index url set mxnet gluon repo jupyter notebook接下來使用 conda 建立虛擬環境並安裝所需軟體 如 mxnet和 d2lzh 包 conda env create f environm...
學習環境搭建
之前在行動硬碟上安裝了ubuntu1604,然後是cuda cudnn anaconda opencv caffe,在之前的部落格中都有記錄,當然還是去官網看install tutorial之類的,少走彎路,遇到問題baidu google。然後隨著對深度學習的學習要使用tensorflow pyt...