1. 程式人生 > >Java Socket 程式設計學習(3)

Java Socket 程式設計學習(3)

Java Socket 程式設計學習,利用DatagramSocket和DatagramPacket實現UDP資料傳輸

場景描述:

客戶端建立資料包,繫結伺服器地址和埠,向伺服器傳送資料;伺服器繫結埠,從埠接受資料

伺服器程式碼:

ServerBean類

package yang.socket.udp;

import java.io.IOException;

import java.net.DatagramPacket;

import java.net.InetAddress;

import java.net.InetSocketAddress;

import java.net.DatagramSocket;

import java.net.SocketException;

import java.net.UnknownHostException;

public class ServerBean {

	// 描述UDP通訊的DatagramSocket物件

	private DatagramSocket ds;

	// 用來封裝通訊字串

	private byte buffer[];

	// 伺服器端的埠號

	private int serverport;

	// 通訊內容

	private String content;

	// 描述通訊地址,此類表示網際網路協議 (IP) 地址。

	private InetAddress addr;

	// 此類實現 IP 套接字地址(IP 地址 + 埠號)

	private InetSocketAddress sd;

	// 此類表示資料報包

	private DatagramPacket dp;

	// 以下是各屬性的Get和Set型別方法

	public DatagramSocket getDs() {
		
		return ds;
	}

	public void setDs(DatagramSocket ds) {
		
		this.ds = ds;
	}

	public byte[] getBuffer() {
		
		return buffer;
	}

	public void setBuffer(byte[] buffer) {
		
		this.buffer = buffer;
	}

	public int getServerport() {
		
		return serverport;
	}

	public void setServerport(int serverport) {
		
		this.serverport = serverport;
	}

	public String getContent() {
		
		return content;
	}

	public void setContent(String content) {
		
		this.content = content;
	}

	public InetAddress getAddr() {
		
		return addr;
	}

	public void setAddr(InetAddress addr) {
		
		this.addr = addr;
	}

	public InetSocketAddress getSd() {
		
		return sd;
	}

	public void setSd(InetSocketAddress sd) {
		
		this.sd = sd;
	}

	public DatagramPacket getDp() {
		
		return dp;
	}

	public void setDp(DatagramPacket dp) {
		
		this.dp = dp;
	}

	public ServerBean(int port, InetAddress addr) throws SocketException,
			UnknownHostException

	{

		this.buffer = new byte[1024];

		this.serverport = port;

		this.content = "";

		this.ds = null;

		this.setAddr(addr);

		this.dp = null;

		this.sd = null;

	}

	public void bind(InetAddress addr, int port) throws SocketException,
			UnknownHostException {

		// 建立資料報套接字並將其繫結到本地主機上的指定埠

		ds = new DatagramSocket(null);

		// 建立地址,本地地址

		sd = new InetSocketAddress(addr, port);

		// 繫結本地地址,在此埠接受訊息

		ds.bind(sd);
		
		// System.out.println("伺服器繫結埠 " + port);
		
		// System.out.println(ds.getLocalSocketAddress());
	}

	public void listenClient() throws IOException

	{

		// 在迴圈體裡接收訊息

		while (true)

		{

			// 初始化DatagramPacket型別的變數DatagramPacket,用來接收長度為 length 的資料包

			dp = new DatagramPacket(buffer, buffer.length);

			// 接收訊息,並把訊息通過dp引數返回

			ds.receive(dp);

			content = new String(dp.getData(), 0, dp.getLength());

			System.out.println(content);

			System.out.println("Message From " + dp.getSocketAddress());
			

		}

	}

}

UDPServer類

package yang.socket.udp;

import java.io.IOException;
import java.net.InetAddress;

public class UDPServer {
	
	public static int serverport;
	
	public static InetAddress localaddr;

	public static void main(String args[]) throws IOException

	{
		serverport = 1986;
		
		localaddr = InetAddress.getLocalHost();
		
		System.out.println("伺服器端啟動,繫結埠 " + serverport);

		ServerBean server = new ServerBean(serverport, localaddr);
		
		server.bind(localaddr, serverport);

		System.out.println("Message Recevied:");

		server.listenClient();

	}

}

客戶端程式碼:

ClientBean類

package yang.socket.udp;

import java.io.IOException;

import java.net.DatagramPacket;

import java.net.InetSocketAddress;

import java.net.DatagramSocket;

import java.net.InetAddress;

import java.net.SocketException;

import java.net.UnknownHostException;

public class ClientBean {

	// 描述UDP通訊的DatagramSocket物件,表示用來發送和接收資料報包的套接字

	private DatagramSocket ds;

	// 此類表示資料報包
	
	private DatagramPacket dp;
	
	//此類實現 IP 套接字地址(IP 地址 + 埠號)
	
	private InetSocketAddress sd;

	// 用來封裝通訊字串

	private byte buffer[];

	// 客戶端的埠號

	private int clientport;

	// 伺服器端的埠號

	private int serverport;

	// 通訊內容

	private String content;

	// 描述通訊地址,此類表示網際網路協議 (IP) 地址。

	private InetAddress localaddr;
	
	private InetAddress serveraddr;

	// 以下是各屬性的Get和Set型別方法


	public DatagramSocket getDs() {
		
		return ds;
	}

	public void setDs(DatagramSocket ds) {
		
		this.ds = ds;
	}

	public DatagramPacket getDp() {
		
		return dp;
	}

	public void setDp(DatagramPacket dp) {
		
		this.dp = dp;
	}

	public InetSocketAddress getSd() {
		
		return sd;
	}

	public void setSd(InetSocketAddress sd) {
		
		this.sd = sd;
	}

	public byte[] getBuffer() {
		
		return buffer;
	}

	public void setBuffer(byte[] buffer) {
		
		this.buffer = buffer;
	}

	public int getClientport() {
		
		return clientport;
	}

	public void setClientport(int clientport) {
		
		this.clientport = clientport;
	}

	public int getServerport() {
		
		return serverport;
	}

	public void setServerport(int serverport) {
		
		this.serverport = serverport;
	}

	public String getContent() {
		
		return content;
	}

	public void setContent(String content) {
		
		this.content = content;
	}

	public InetAddress getLocaladdr() {
		
		return localaddr;
	}

	public void setLocaladdr(InetAddress localaddr) {
		
		this.localaddr = localaddr;
	}

	public InetAddress getServeraddr() {
		
		return serveraddr;
	}

	public void setServeraddr(InetAddress serveraddr) {
		
		this.serveraddr = serveraddr;
	}

	public ClientBean(int clientport, int serverport, InetAddress serveraddr, InetAddress localaddr) throws SocketException,
			UnknownHostException
	{

		this.buffer = new byte[1024];

		this.clientport = clientport;

		this.serverport = serverport;
		
		this.content = "";
		
		this.ds = null; 
		
		this.serveraddr = serveraddr;
		
		this.localaddr = localaddr;
		
		this.dp = null;
		
		this.sd = null;

	}

	public void bind(InetAddress addr, int clientport) throws SocketException, UnknownHostException{
		
		// 建立資料報套接字並將其繫結到本地主機上的指定埠
		ds =  new DatagramSocket(null); 
		//建立地址,本地地址
		sd = new InetSocketAddress(addr, clientport);
		//將此 DatagramSocket 繫結到特定的地址和埠
		ds.bind(sd);
	}
	
	public void sendToServer() throws IOException

	{

		buffer = content.getBytes();

		// 構造資料報包,用來將長度為 length的包傳送到指定主機上的指定埠號。
		dp = new DatagramPacket(buffer, content.length(), serveraddr, serverport);
		
		// 傳送資料包
		ds.send(dp);

	}

}

UDPClient類
package yang.socket.udp;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.net.InetAddress;

public class UDPClient implements Runnable

{
	public static String content;
	
	public static int clientport;
	
	public static int serverport;
	
	public static InetAddress serveraddr;
	
	public static InetAddress localaddr;

	public static ClientBean client;

	public void run()

	{
		try

		{
			// 設定傳送訊息體內容
			client.setContent(content);
			// 傳送訊息
			client.sendToServer();

		}

		catch (Exception ex)

		{

			System.err.println(ex.getMessage());

		}
		
	}

	public static void main(String args[]) throws IOException

	{

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		clientport = 1985;

		serverport = 1986;
		
		//傳送的serverIP地址
		byte[] bs = new byte[] { (byte) 192, (byte) 168, (byte) 30, (byte) 13 };
		
		serveraddr = InetAddress.getByAddress(bs);
		
		localaddr = InetAddress.getLocalHost();
		
		client = new ClientBean(clientport, serverport, serveraddr, localaddr);
		//講套接字繫結到本地
		client.bind(localaddr, clientport);

		System.out.println("客戶端啟動");
		
		System.out.print("Server Address: ");
		//獲取套接字連線的地址
		System.out.print("HostName " + client.getServeraddr().getHostName());
		
		System.out.print(" Address " + client.getServeraddr().getHostAddress());
		
		System.out.print(" Port " + client.getServerport() + "\n");

		System.out.print("Local Address:  ");
		//獲取套接字繫結的本地地址
		System.out.print("HostName " + client.getDs().getLocalAddress().getHostName());
		
		System.out.print(" Address " + client.getDs().getLocalAddress().getHostAddress());
		
		System.out.print(" port " + client.getDs().getLocalPort() + "\n");
		
		System.out.println("請輸入傳送內容,回車傳送,鍵入end時傳送結束");

		while (true)

		{

			// 接收使用者輸入
			content = br.readLine();

			// 如果是end或空,退出迴圈

			if (content == null || content.equalsIgnoreCase("end")
					|| content.equalsIgnoreCase(""))

			{
				break;
			}
			
			// 開啟新執行緒,傳送訊息
			// 每次輸入一次訊息,就新建一個執行緒和連線
			new Thread(new UDPClient()).start();
			

		}
		
		System.out.println("連線套接字斷開關閉");
		
		client.getDs().disconnect();
		
		client.getDs().close();
		
	}

}

測試執行:

UDPClient

客戶端啟動
Server Address: HostName Lenovo-PC Address 192.168.30.13 Port 1986
Local Address:  HostName Lenovo-PC Address 192.168.30.13 port 1985
請輸入傳送內容,回車傳送,鍵入end時傳送結束
nihao
this is a udp test
end
連線套接字斷開關閉

UDPServer
伺服器端啟動,繫結埠 1986
Message Recevied:
nihao
Message From /192.168.30.13:1985
this is a udp test
Message From /192.168.30.13:1985