TCP和UDP實現簡單一對一通訊

愛編碼的小學生發表於2018-07-01

TCP

實現A(客戶端)向B(伺服器)傳送訊息,B向A回覆訊息

首先
A->B(第一次發訊息)
因為是第一次傳送訊息,所以要先建立連線,則需要B的IP和B的埠號
同時,B會在指定的埠監聽,監聽到了先進行連線(三次握手連線,若是連線不上,A就會報錯)
連線成功後,B再通過A發給B的Socket讀取第一次傳送的訊息
B->A

因為是第一發訊息成功,保留了socket,所以後續就不需要再連線,直接進行傳送和接收

在後續的通訊中,兩邊都建立一個只接收訊息執行緒不停的接收訊息(不用建立傳送訊息的執行緒),
也就是說,A向B傳送訊息,B接收訊息的執行緒接收到了,然後B又向A回覆訊息,A接收訊息的執行緒接收到了,依次迴圈

注意:A與B不再進行通訊時,需要關閉socket(socket.close())


上程式碼:

服務端

package text;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class Server{
	public static void main(String[] args) throws Exception {
		ServerSocket server = new ServerSocket(888); 
		//監聽埠
		Socket socket = server.accept(); 
		InputStreamReader reader 
			= new InputStreamReader(socket.getInputStream());
		BufferedReader buffer_reader=new BufferedReader(reader); 
		PrintWriter writer=new PrintWriter(socket.getOutputStream()); 
		//讀取客戶端發來的資訊
		String request = buffer_reader.readLine(); 
		System. out .println("Client say:" + request); 
		String line="Hello,too!"; 
		writer.println(line);
		writer.flush();
		writer.close(); 
		buffer_reader.close(); 
		//關閉socket
		socket.close(); 
		server.close();	
	}
}

客戶端

package text;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {
	public static void main(String[] args) throws UnknownHostException, IOException {
		//建立客戶端傳送socket 服務端IP和服務端Port
		Socket socket = new Socket("127.0.0.1",888); 
		InputStreamReader reader = new InputStreamReader(socket.getInputStream());
		BufferedReader buffer_reader = new BufferedReader(reader); 
		PrintWriter writer = new PrintWriter(socket.getOutputStream()); 
		String readline = "Hello!"; 
		writer.println(readline); 
		writer.flush(); 
		//讀取服務端回覆的訊息
		String response = buffer_reader.readLine(); 
		System. out .println("Server say:"+ response); 
		writer.close(); 
		buffer_reader.close(); 
		socket.close(); 
	}
}

-------------------------------------------------分割線------------------------------------------------------------------

UDP

A(客戶端)向B(服務端)傳送訊息,B向A回覆訊息

首先
A->B

A要有B的IP和B的埠號,A例項化一個傳送訊息的socket,不需要繫結埠和IP,

但是資料包Paceket裡面要寫上B的埠和B的IP

系統會自動找空閒埠將A的找到的這個傳送訊息的空閒埠資訊和A的IP封裝到socket,通過socket傳送出去


B->A
B接收到這個資料包(根據UDP資料包協議,資料包裡面包含了源IP和源埠號以及目的地址和目的埠,以及內容)

通過DatagramPacket.getSocketAddress()方法解析出A的SocketAddress(也就是A的套接字地址)

資料包格式:



繼續上程式碼:

客戶端

package text;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class Client { 
	public static void main(String[] args) {  
		try { 
			// 建立傳送方的套接字,IP預設為本地,埠號隨機
			DatagramSocket sendSocket = new DatagramSocket(); 
			// 確 定要傳送的訊息: 
			String mes = "你好!接收方!"; 
			// 由於資料包的資料是以字元陣列傳的形式儲存的,所以傳轉資料 
			byte[] buf = mes.getBytes(); 
			// 確定傳送方的IP地址及埠號,地址為本地機器地址 
			int port = 8888; 
			InetAddress ip = InetAddress. getLocalHost ();
			// 建立傳送型別的資料包: 
			DatagramPacket sendPacket = new DatagramPacket(buf, buf.length, ip, port); 
			// 通過套接字傳送資料: 
			sendSocket.send(sendPacket); 
			// 確定接受反饋資料的緩衝儲存 器,即儲存資料的位元組陣列 
			byte[] getBuf = new byte[1024]; 
			// 建立接受型別的資料包 
			DatagramPacket getPacket = new DatagramPacket(getBuf, getBuf.length); 
			// 通過套接字接受資料
			sendSocket.receive(getPacket); 
			// 解析反饋的訊息,並列印 
			String backMes = new String(getBuf, 0, getPacket.getLength()); 
			System.out.println("接受方返回的訊息:" + backMes); 
			// 關閉套接字 
			sendSocket.close(); 
			}catch (Exception e) { 
				e.printStackTrace(); 
			} 
		}
}

服務端

package text;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketAddress;

public class Server { 
	public static void main(String[] args) { 
		try { 
			InetAddress ip = InetAddress. getLocalHost (); 
			int port = 8888; 
			// 建立接收方的套接字,並制定埠號和IP地址
			DatagramSocket getSocket = new DatagramSocket(port, ip); 
			// 確定資料包接受的資料的陣列大小 
			byte[] buf = new byte[1024]; 
			// 建立接受型別的資料包,資料將 儲存在buf中 
			DatagramPacket getPacket = new DatagramPacket(buf, buf.length); 
			// 通過套接字接收資料 
			getSocket.receive(getPacket); 
			String getMes= new String(buf,0, getPacket.getLength()); 
			System.out.println("對方傳送的訊息:" + getMes); 
			InetAddress sendIP = getPacket.getAddress();
			int sendPort = getPacket.getPort(); 
			System.out.println("對方的地址是:" + sendIP.getHostAddress() + ":" + sendPort); 
			// 通過資料包得到傳送方的套接字地址 
			SocketAddress sendAddress = getPacket.getSocketAddress(); 
			String feedback = "接收方說:我收到了!"; 
			byte[] backBuf = feedback.getBytes(); 
			DatagramPacket sendPacket = new DatagramPacket(backBuf, backBuf.length, sendAddress); 
			getSocket.send(sendPacket); 
			getSocket.close(); 
			} catch (Exception e) { 
				e.printStackTrace(); 
			} 
		} 
	}



在此基礎上,我自己在借鑑網上資料,自己編寫了一個基於TCP協議的聊天室,能夠簡單實現登入、註冊、群聊、私聊、歷史訊息檢視,原始碼下載地址 https://download.csdn.net/download/qq_37513473/10509044


另附一下資料庫表

user表

message表


以上為我自己對TCP和UDP通訊使用方法的理解,若有不足之處歡迎大家多多指教。

相關文章