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

Java Socket 程式設計學習(4)

Java 利用Socket實現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() throws SocketException,
			UnknownHostException {

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

		ds = new DatagramSocket(null);

		// 建立地址,本地地址

		sd = new InetSocketAddress(addr, serverport);

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

		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());
			
			if(content.equalsIgnoreCase("end")){
				
				System.out.println("The Message is over, client socket has closed.");
			}
			

		}

	}

}

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();

		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() throws SocketException, UnknownHostException{
		
		// 建立資料報套接字並將其繫結到本地主機上的指定埠
		ds =  new DatagramSocket(null); 
		//建立地址,本地地址
		sd = new InetSocketAddress(localaddr, 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;

import java.net.SocketException;

import java.net.UnknownHostException;

class ClientBeanThread implements Runnable{
	
	private ClientBean client;
	
	public ClientBeanThread(int clientport, int serverport, InetAddress serveraddr, InetAddress localaddr) throws SocketException, UnknownHostException{

		this.client = new ClientBean(clientport, serverport, serveraddr, localaddr);;
	}

	public ClientBean getClient() {
		
		return client;
	}

	public void setClient(ClientBean client) {
		
		this.client = client;
	}

	public void SendMessage() throws IOException{
		
		client.sendToServer();

	}
	
	public void bind() throws SocketException, UnknownHostException{
		
		client.bind();
	}
	
	public void setContent(String content){
		
		client.setContent(content);
		
	}
	
	public void run() {

		try {

			SendMessage();

		}catch (IOException e) {

			e.printStackTrace();
		}
	}
	
}
	
	public class UDPClient{
		
		public static int clientport;
		
		public static int serverport;
		
		public static String content;
		
		static byte[]  ip;
		
		static InetAddress serveraddr;
		
		static InetAddress localaddr;
		
		static BufferedReader input;
		
		static ClientBeanThread client;
		
		public static void main(String args[]) throws IOException, InterruptedException

		{			
			
			clientport = 1985;

			serverport = 1986;
			
			ip = new byte[] { (byte) 192, (byte) 168, (byte) 30, (byte) 13 };
			
			serveraddr = InetAddress.getByAddress(ip);
			
			localaddr = InetAddress.getLocalHost();
			
			input = new BufferedReader(new InputStreamReader(System.in));
			
			client = new ClientBeanThread(clientport, serverport, serveraddr, localaddr);
			
			client.bind();
			
			System.out.println("客戶端啟動");
			
			System.out.print("Server Address: ");
			//獲取套接字連線的地址
			System.out.print("HostName " + client.getClient().getServeraddr().getHostName());
			
			System.out.print(" Address " + client.getClient().getServeraddr().getHostAddress());
			
			System.out.print(" Port " + client.getClient().getServerport() + "\n");

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


			while(true){
				
				content = input.readLine();
				
				client.setContent(content);
				
				new Thread(client).start();
				
				if (content.equalsIgnoreCase("end")){
					
					System.out.println("Send is over.");
					
					break;
				}
				
			}
			
			Thread.sleep(2000);
			
			System.out.println("Socket has closed.");
			
			client.getClient().getDs().disconnect();
			
			client.getClient().getDs().close();
		}
	}
	

測試執行:

客戶端

客戶端啟動
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
Send is over.
Socket has closed.

伺服器端
伺服器端啟動,繫結埠 1986
Message Recevied:
nihao
Message From /192.168.30.13:1985
this is a udp test
Message From /192.168.30.13:1985
end
Message From /192.168.30.13:1985
The Message is over, client socket has closed.