TCP和UDP套接字程式設計 (java實現)
阿新 • • 發佈:2018-12-22
在瞭解網路程式設計之前,我們先了解一下什麼叫套接字
套接字即指同一臺主機內應用層和運輸層之間的介面
由於這個套接字是建立在網路上建立網路應用的可程式設計介面
因此也將套接字稱為應用程式和網路之間的應用程式程式設計介面!
關於TCP和UDP這裡就不作太多介紹了,我們知道TCP是面向連線的,UDP是不面向連線的,TCP可靠,UDP不可靠即可!
我們來設計一個應用來示範一下,流程:
- 客戶機從鍵盤讀取一行字串,並通過套接字傳送到伺服器。
- 伺服器從連線的套接字獲取這行字串,並對其進行修改(將小寫轉為大寫),最後再發回客戶端。
- 客戶機讀取到伺服器傳送的修改後的字串,並輸出到螢幕。
不說太多了,直接上程式碼:
TCP套接字程式設計:
客戶端:
package TCP套接字程式設計; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; import java.net.UnknownHostException; public class TCPClient { publicstatic void main(String[] args) throws UnknownHostException, IOException { // 建立兩個String型別的字串用來接收和傳送字元 String sentence; String modifiedSentence; // 建立輸入流,用來接收鍵盤輸入 BufferedReader inFromUser = new BufferedReader(new InputStreamReader( System.in));// 建立一個Scoket型的clientScoket用來發起伺服器和客戶機之間的連線 String postname = "169.264.187.20";// 客戶端ip地址(請用自己電腦的ip地址代替) Socket clientSocket = new Socket(postname, 6789); // 建立向伺服器傳送資訊的輸出流 DataOutputStream outToServer = new DataOutputStream( clientSocket.getOutputStream()); // 建立輸入流,用來接收來自伺服器的位元組流 BufferedReader inFromServer = new BufferedReader(new InputStreamReader( clientSocket.getInputStream())); // 讀取要傳送的資料 sentence = inFromUser.readLine(); // 向伺服器傳送資料 outToServer.writeBytes(sentence + '\n'); // 獲取從伺服器接收的資料 modifiedSentence = inFromServer.readLine(); // 列印接收資料 System.out.println("From Server:" + modifiedSentence); } }
伺服器端:
package TCP套接字程式設計; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; public class TCPServer { public static void main(String[] args) throws IOException { // 從客戶端接收的字串,要傳送給客戶端的字串 String clientSentence; String serverSentence; // 伺服器開啟6789埠,建立連線 ServerSocket welcomeSocket = new ServerSocket(6789); while (true) {// 伺服器的6789埠一直開啟 // 用此連線來獲取和傳送客戶端資料流 Socket connectionSocket = welcomeSocket.accept(); // 獲取來自客戶端的資料流 BufferedReader inFromClient = new BufferedReader( new InputStreamReader(connectionSocket.getInputStream())); // 準備傳送更改後的資料流 DataOutputStream outToClient = new DataOutputStream( connectionSocket.getOutputStream()); // 讀取收到的資料 clientSentence = inFromClient.readLine(); // 將讀取到的資料都中的小寫字母改為大寫字母 serverSentence = clientSentence.toUpperCase() + '\n'; // 傳送修改後的資料給客戶端 outToClient.writeBytes(serverSentence); } } }
UDP套接字程式設計:
客戶端:
package UDP套接字程式設計; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class UDPClient { public static void main(String[] args) throws IOException { // 讀取鍵盤輸入的位元組流 BufferedReader inFromUser = new BufferedReader(new InputStreamReader( System.in)); // 為客戶端創造一個傳輸資訊的門,但是並沒有像TCP那樣建立連線 DatagramSocket clientSocket = new DatagramSocket(); // 呼叫DNS查詢,得到主機名對應的IP地址 InetAddress IPAddress = InetAddress.getByName(null);//null的話得到的是自己的IP地址 System.out.println(IPAddress); // 定義需要傳送的位元組陣列 byte[] sendData = new byte[1024];// 不能動態開陣列。。。 // 定義需要接收的位元組陣列 byte[] receiveData = new byte[1024]; // 將從鍵盤接收到的資料先用字串存起來 String sentence = inFromUser.readLine(); // 將字串轉為位元組存入sendData sendData = sentence.getBytes(); // 準備傳送UDP資料報,裡面包含傳送內容和目的地址等資訊 DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 9878); // 用這個門來發送資料報 clientSocket.send(sendPacket); // 準備獲取從伺服器返回的資料報 DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); // 用這個門來接收伺服器發的資料報 clientSocket.receive(receivePacket); // 將獲取的資料報轉換為String型別 String modifiedSentence = new String(receivePacket.getData()); // 列印從伺服器收到的內容 System.out.println("From Server:" + modifiedSentence + '\n'); // 關閉這個門 clientSocket.close(); } }
伺服器端:
package UDP套接字程式設計; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class UDPServer { public static void main(String[] args) throws IOException { // 建立一個門,在9878埠 DatagramSocket serverSocket = new DatagramSocket(9878); while (true) { // 定義接收資料的位元組陣列 byte[] receiveData = new byte[1024]; // 定義傳送資料的位元組陣列 byte[] sendData = new byte[1024]; // 建立UDP資料報物件,準備接收UDP資料報 DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); // 接收UDP資料報 serverSocket.receive(receivePacket); // 將收到的UDP資料報轉換為String字串 String sentence = new String(receivePacket.getData()); // 得到接收到的UDP資料報的源IP地址 InetAddress IPAddress = receivePacket.getAddress(); // 得到接收到的UDP資料報的源埠號 int port = receivePacket.getPort(); // 小寫字母全部變為大寫字母 String capitalized = sentence.toUpperCase(); // 將字串轉換為位元組陣列以便傳送 sendData = capitalized.getBytes(); // 準備傳送位元組陣列,做好封裝UDP資料報工作 DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port); // 通過門正式傳送UDP資料報 serverSocket.send(sendPacket); } } }
分析:
先執行伺服器端程式碼,這樣伺服器才能工作:開啟相應埠,做好接收資料的準備
然後執行客戶端程式碼,傳送資料
伺服器工作時,對應埠一直的開啟的,隨時準備響應客戶端的請求
參考書籍:《計算機網路自頂向下方法》