摘要
TCP/IP協議族是構建互連網的基石協議。在互連網中,從一台電腦向另外一台電腦傳送資料,資料包可以通過兩種協議傳輸。其中一種就是傳輸控制通訊協定(Transmission Control Protocol,TCP)。TCP能夠確保資料的傳送,也確保資料包以它們正確的順序傳送,是一種提供可靠串連的傳送協議。由於Java語言支援基於流的通訊,即是用TCP協議進行傳輸,所以本次的課程設計將基於Java語言,設計出一個可以發送TCP資料包的程式。 關鍵字
傳輸控制通訊協定(TCP),Java,通訊端(Socket),IP,連接埠(Port) 1 引言
在互連網的四層協議中,TCP位於IP層之上,應用程式層之下的傳輸層。不同主機的應用程式層之間經常需要可靠的、像管道一樣的串連。而連線導向、提供可靠傳輸的TCP協議則正好能夠滿足這一需求。因此被廣泛利用。
掌握TCP資料包的發包原理和功能的實現,有利於我們能夠更進一步地學習和利用更多應用程式層上的應用和技術,如檔案傳送(FTP)、遠程登入(RemoteLogin)等。
本次課程設計要求我們能夠實現以下效果:
(1) 以命令列形式運行:
SendTCP source_IP source_port dest_ip dest_port
其中,SendTCP為程式名,source_IP為源端IP地址,source_port為源連接埠,dest_ip 為目的IP地址,dest_port為目的連接埠
(2) 其他的TCP頭部參數請自行設定。
(3) 資料欄位為“Thisis my homework of network ,I am happy!”.
(4) 成功發送後在螢幕上輸出“SendOK”。 2 總體設計 2.1 系統或演算法架構設計 (1) 服務端的設計架構(發送資料區段方)
(2) 用戶端的設計架構(發送反饋資訊方)
2.2 功能設計
在本次課程設計中,要求發送一段資料包,裡麵包含一段資料資訊。同時,為了驗證資料包發送成功,還需要進行驗證。因此需要實現至少發送資料包和驗證發送是否成功的兩項功能。建立服務端發送資料區段,用戶端接收資料區段並發送反饋資訊。當它們分別運行在不同的主機上,運行程式。根據程式的運行情況,便能驗證這兩項功能。
在服務端,我們首先建立對源連接埠的監聽。當用戶端成功串連到源連接埠時,服務端即按要求發送資料區段“This is my homework of network ,I amhappy!”到目的IP、連接埠。用戶端,建立連接埠的監聽,當收到資料區段後發送“SendOK!”反饋給服務端。通過這樣的資料包傳送的資料,便能實現以上兩種功能,見圖3。要注意的是,服務端的源IP、連接埠即為用戶端的目的IP、連接埠;服務端的目的IP、連接埠即為用戶端的源IP、連接埠。
2.3 平台設計
本次的課程設計在Java語言的平台上利用Java語言實現。為了實現在兩台電腦發送資料包的功能。本次實驗採用了物理機和虛擬機器類比在同一個區域網路中。其中物理機採用Windows 8.1系統,IP地址為192.168.126.53,而虛擬機器則採用Windows XP系統,IP地址為192.168.126.52。如圖4所示。 2.4 資料結構的設計
本次實驗採用了String類型儲存字元,而連接埠號碼則採用Int類型。而由於文本I/O需要編碼和解碼,所以,二進位I/O的效率比文本I/O的效率更高。因此最好使用二進位I/O在服務端和用戶端之間進行資料轉送,以便提高效率。因此,在讀入和寫入分別採用了DataInputStream和DataOutStrea這兩個類。 2.5 介面設計
根據題目要求,程式運行時必須輸入4個參數:源IP、源連接埠、目的IP、目的連接埠。程式開始時會判斷是否已經輸入了4個參數,如果沒有輸入四個參數,或輸入錯誤,輸出錯誤提示,如圖5所示。
3. 詳細設計(按照實際情況分小點,詳細書寫整個的設計流程以及核心原始碼) 3.1 參數讀入
不論是用戶端還是服務端,根據要求,都需要讀入IP和連接埠資訊。而服務端的源IP、連接埠即為用戶端的目的IP、連接埠;服務端的目的IP、連接埠即為用戶端的源IP、連接埠。 [java] view plain copy print ? String sourceIP = args[0];//源IP int sourcePort = Integer.parseInt(args[1]);//源連接埠 String destinationIP = args[2];//目的IP int destinationPort = Integer.parseInt(args[3]);//目的連接埠
String sourceIP = args[0];//源IP int sourcePort = Integer.parseInt(args[1]);//源連接埠 String destinationIP = args[2];//目的IP int destinationPort = Integer.parseInt(args[3]);//目的連接埠
3.2 建立通訊端
無論是服務端還是用戶端都需要建立通訊端(Socket)。建立通訊端有兩種方法,一種是主動發送資訊的。例外一種則是被動接收資訊再發出反饋(監聽)。在本次課程實驗中,無論是兩端既需用到主動發資訊又需要用到監聽。 [java] view plain copy print ? //主動發送資訊,發送方向為目的IP的目的連接埠 Socket socket = new Socket(destinationIP, destinationPort); DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream()); dataOutputStream.writeUTF("Response Please!"); //監聽,接收發給源IP的源連接埠資訊。 ServerSocket serverSocket = new ServerSocket(sourcePort); socket = serverSocket.accept();
//主動發送資訊,發送方向為目的IP的目的連接埠Socket socket = new Socket(destinationIP, destinationPort);DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());dataOutputStream.writeUTF("Response Please!");//監聽,接收發給源IP的源連接埠資訊。ServerSocket serverSocket = new ServerSocket(sourcePort); socket = serverSocket.accept();3.3 發送或接收資料
作為本次課程實驗的重點,發送和接收是否成功是本次課程設計是否成功的關鍵。為了保證程式能夠成功運行,本次發送的資料均採用位元據流。 [java] view plain copy print ? //發送資訊 DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream()); dataOutputStream.writeUTF("Response Please!"); //接收資訊 DataInputStream dataInputStream = new DataInputStream(socket.getInputStream()); String dataSegment=dataInputStream.readUTF();
//發送資訊DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());dataOutputStream.writeUTF("Response Please!"); //接收資訊DataInputStream dataInputStream = new DataInputStream(socket.getInputStream()); String dataSegment=dataInputStream.readUTF();3.4 服務端功能實現
服務端在本次課程設計中,主要負責往目的通訊端(目的IP+連接埠)發送資料區段“Thisis my homework of network ,I am happy! ”,並接收來時目的通訊端返回的資料區段“SendOK!”,見圖6。 [java] view plain copy print ? //記錄源和目的通訊端的資訊 String sourceIP = args[0]; int sourcePort = Integer.parseInt(args[1]); String destinationIP = args[2]; int destinationPort = Integer.parseInt(args[3]); //建立監聽 ServerSocket serverSocket = new ServerSocket(sourcePort); Socket socket = serverSocket.accept(); //接收來自用戶端的資訊 DataInputStream dataInputStream = new DataInputStream(socket.getInputStream()); //發送資訊 String dataSegment = "This is my homework of network ,I am happy!"; DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream()); dataOutputStream.writeUTF(dataSegment); //接收成功資訊 socket = new Socket(destinationIP, destinationPort); dataOutputStream = new DataOutputStream(socket.getOutputStream()); dataOutputStream.writeUTF("Successfully Received!"); dataInputStream = new DataInputStream(socket.getInputStream()); dataSegment=dataInputStream.readUTF(); PrintMessage("接收到來自" + socket.getInetAddress().toString().substring(1) + "," + socket.getPort() + "號連接埠的資訊"); PrintMessage("資訊內容為:" + dataSegment); //關閉流 dataInputStream.close(); dataOutputStream.close(); socket.close(); serverSocket.close();
//記錄源和目的通訊端的資訊String sourceIP = args[0];int sourcePort = Integer.parseInt(args[1]);String destinationIP = args[2];int destinationPort = Integer.parseInt(args[3]);//建立監聽ServerSocket serverSocket = new ServerSocket(sourcePort);Socket socket = serverSocket.accept();//接收來自用戶端的資訊DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());//發送資訊String dataSegment = "This is my homework of network ,I am happy!";DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream()); dataOutputStream.writeUTF(dataSegment); //接收成功資訊socket = new Socket(destinationIP, destinationPort);dataOutputStream = new DataOutputStream(socket.getOutputStream());dataOutputStream.writeUTF("Successfully Received!");dataInputStream = new DataInputStream(socket.getInputStream());dataSegment=dataInputStream.readUTF();PrintMessage("接收到來自" + socket.getInetAddress().toString().substring(1) + "," + socket.getPort() + "號連接埠的資訊");PrintMessage("資訊內容為:" + dataSegment);//關閉流dataInputStream.close();dataOutputStream.close();socket.close();serverSocket.close();3.5 用戶端功能實現
用戶端在本次課程設計中,主要負責的是接收來自服務端的資訊,並發出反饋資訊“Send OK!”,見圖7。
[java] view plain copy print ? //嘗試串連 Socket socket = new Socket(destinationIP, destinationPort); DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream()); dataOutputStream.writeUTF("Response Please!"); //獲得回應 DataInputStream dataInputStream = new DataInputStream(socket.getInputStream()); String dataSegment = dataInputStream.readUTF(); PrintMessage("接收到來自" + socket.getInetAddress().toString().substring(1) + "," + socket.getPort() + "號連接埠的資訊"); PrintMessage("資訊內容為:" + dataSegment); //回複 ServerSocket serverSocket = new ServerSocket(sourcePort); socket = serverSocket.accept(); dataOutputStream = new DataOutputStream(socket.getOutputStream()); dataOutputStream.writeUTF("Send OK!");
//嘗試串連 Socket socket = new Socket(destinationIP, destinationPort); DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream()); dataOutputStream.writeUTF("Response Please!"); //獲得回應DataInputStream dataInputStream= new DataInputStream(socket.getInputStream());String dataSegment = dataInputStream.readUTF();PrintMessage("接收到來自" + socket.getInetAddress().toString().substring(1) + "," + socket.getPort() + "號連接埠的資訊"); PrintMessage("資訊內容為:" + dataSegment);//回複ServerSocket serverSocket = new ServerSocket(sourcePort);socket = serverSocket.accept();dataOutputStream = new DataOutputStream(socket.getOutputStream());dataOutputStream.writeUTF("Send OK!");4 總結 4.2 存在的問題
(1) 命令列介面不夠美觀且操作性不夠強
(2) 每次都輸入4個參數太麻煩了 4.3 改進的方法
(1) 改用圖形介面,並美化介面。但可能速度上不夠現在的快。
(2) 仿照命令提示字元(cmd),可以預設輸入。 【參考文獻】
[1]Y.Daniel Liang.Java語言程式設計(基礎篇)[M].李娜,譯.北京:機械工業出版社,2011:527-535
[2]Y.Daniel Liang.Java語言程式設計(進階篇)[M].李娜,譯.北京:機械工業出版社,2011:258-264
[3]謝希仁.電腦網路簡明教程(第二版)[M].北京:電子工業出版社,2013:123-143