Java學習總結2——網絡編程

Java網絡編程

1、構造ip地址:

InetAddress ip = InetAddress.getByName(host);//host能夠是計算機名字也能夠是IP地址如127.0.0.1
複製代碼

2、Socket套接字

在程序中使用scoket進行通訊,使用socket通訊須要指定IP、端口、協議(UDP、TCP);數據發送分爲兩步:一、第一步是監聽(等待數據發送過來),用來接收數據,需指定監聽的端口;二、第二部是發送(須要指定發送到哪一個計算機:IP地址,該計算機的哪一個程序:Port號)。編程

socket中分爲發送端和接收端:發送端通常爲客戶端,接收端通常爲服務端。數組

通常有多個客戶端,一個服務端。bash

3、使用UDP協議

UDP協議無需創建鏈接,直接向接收端發送數據報,不用考慮對方是否接收到數據報,只須要向接收方發送就行,至於接收方有沒有接收到發送端不用管。因此使用UDP協議進行網絡數據傳輸是不可靠的,可是速度快!微信

使用UDP協議開發發送端: 用DatagramSocket發送數據:網絡

DatagramSocket ds = new DatagramSocket();//socket套接字
複製代碼

用DatagramPacket做爲包裹(發送的數據內容):socket

byte[] buf = "你好,我想給你發送數據!".getBytes();//字節數組
int length = buf.length;//發送的長度
InetAddress address = InetAddress.getByName("127.0.0.1");//指定接收端的IP地址
int port = 7878;//指定接收端的監聽端口號,與接收端對應

DatagramPacket dp = new DatagramPacket(buf, length, address, port);//待發送的包裹
複製代碼

send()發送數據,close()釋放資源。ide

ds.send(dp);//發送1次
//ds.send(dp);//發送2次
...
//ds.send(dp);//發送n次
ds.close();//發送完畢,釋放資源
複製代碼

舉個栗子🌰:ui

//UDP發送端
public class Demo2_UDP_Send {
	public static void main(String[] args) throws Exception {
		DatagramSocket ds = new DatagramSocket();//socket套接字
		
		byte[] buf = "你好,我想給你發送數據!".getBytes();//字節數組
		int length = buf.length;//發送數據的長度
		InetAddress address = InetAddress.getByName("127.0.0.1");//指定接收端的IP地址
		int port = 7878;//指定接收端的端口號
		
		DatagramPacket dp = new DatagramPacket(buf, length, address, port);//待發送的包裹
		
		ds.send(dp);//發送
		ds.close();//發送完畢,釋放資源
	}
}
複製代碼

使用UDP協議開發接收端: 用DatagramSocket來監聽發送端發送過來的數據:this

DatagramSocket ds = new DatagramSocket(7878);//接收端的監聽端口
複製代碼

用DatagramPacket做爲接收數據的容器:spa

byte[] buf = new byte[1024];
int length = buf.length;
DatagramPacket dp = new DatagramPacket(buf, length);//直接做爲接收數據的容器
複製代碼

receive()接收數據,程序會在這裏等待數據的到來:

ds.receive(dp);//等待數據到來
複製代碼

與發送端同樣,接收到數據以後一樣須要釋放對象ds的資源:

ds.close();//接收到數據,釋放資源
複製代碼

舉個栗子🌰:

//UDP接收端
public class Demo3_UDP_Receive {
	public static void main(String[] args) throws Exception {
		DatagramSocket ds = new DatagramSocket(7878);//接收端的監聽端口
		
		byte[] buf = new byte[1024];
		int length = buf.length;
		DatagramPacket dp = new DatagramPacket(buf, length);//直接做爲接收數據的容器
		
		ds.receive(dp);//等待數據到來
		
		String str = new String(dp.getData(), 0, dp.getLength());
		System.out.println(str);//輸出發送過來的數據
		
		ds.close();//接收到數據,釋放資源
 	}
}
複製代碼

程序運行結果:

接收端的其餘信息獲取:

dp.getAddress();//獲取發送端的IP地址
dp.getPort();//獲取發送端的端口號
複製代碼

使用UDP協議實現兩個用戶雙向聊天:

一、新建一個SendThread發送線程類:

public class SendThread extends Thread {
	
	private int port;
	public SendThread(int port) {
		this.port=port;
	}
	
	@Override
	public void run() {
		DatagramSocket ds=null;
		try {
			ds = new DatagramSocket();
			Scanner inputstr = new Scanner(System.in);//輸入數據
			
			while (true) {
				String str = inputstr.nextLine();
				if (str.equals("end")) break;
				byte[] buf = str.getBytes();//字節數組
				int length = buf.length;//發送數據的長度
				InetAddress address = InetAddress.getByName("127.0.0.1");//指定接收端的IP地址
				//int port = 7878;//指定接收端的端口號
				
				DatagramPacket dp = new DatagramPacket(buf, length, address, port);//發送包裹
				
				ds.send(dp);//發送
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (ds!=null) {//有數據傳輸,因此須要釋放資源
				ds.close();
			}
		}
		
		
	}
}
複製代碼

二、再建一個ReceiveThread接收線程類:

public class ReceiveThread extends Thread {
	
	private int port;
	public ReceiveThread(int port) {
		this.port=port;
	}
	
	@Override
	public void run() {
		DatagramSocket ds=null;
		try {
			ds = new DatagramSocket(port);//指定端口號來監聽數據,與發送端發送數據包指定的端口相對應
			
			while (true) {
			    byte[] buf = new byte[1024];
			    int length = buf.length;
			    DatagramPacket dp = new DatagramPacket(buf, length);//做爲接收數據的容器
			    ds.receive(dp);//等待數據到來
			    
			    String str = new String(dp.getData(), 0, dp.getLength());
			    System.out.println("收到來自端口"+dp.getPort()+"的消息:"+str);//輸出發送過來的數據
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (ds!=null) {//有數據傳輸,因此須要釋放資源
				ds.close();
			}
		}
	}
}
複製代碼

三、新建Chant_User01類(用戶1):

public class Chant_User01 {
	public static void main(String[] args) {
		new SendThread(7878).start();//用戶1的發送線程,7878端口爲用戶2的接收線程監聽端口
		new ReceiveThread(7879).start();//用戶1的接收線程,7879監聽來自用戶2發送的數據
	}
}
複製代碼

四、新建Chant_User02類(用戶2):

public class Chant_User02 {
	public static void main(String[] args) {
		new ReceiveThread(7878).start();//用戶2的接收線程,7878監聽來自用戶1發送的數據
		new SendThread(7879).start();//用戶2的發送線程,7879端口爲用戶1的接收線程監聽端口
	}
}
複製代碼

實現效果:

用戶1:

用戶1

用戶2:

用戶2

4、使用TCP協議

TCP協議須要經過三次握手創建鏈接,客戶端與服務端之間是一個雙向通道,既能夠發送數據(使用輸出流),也能夠接收數據(使用輸入流)。因此使用TCP協議進行網絡數據傳輸是可靠的,可是速度較慢!

使用TCP協議開發客戶端: 客戶端直接使用Socket,使用輸出流OutputStream寫入數據發送:

//TCP直接使用Socket
Socket s = new Socket("127.0.0.1", 8888);//與TCP接收端創建鏈接
//使用輸出流來傳輸數據
OutputStream output = s.getOutputStream();
output.write("ww.baidu.com".getBytes());//向服務端寫入數據
s.close();
複製代碼

使用TCP協議開發服務端: 服務端使用ServerSocket,accept()等待接收客戶端發送的TCP鏈接請求,與客戶端建立鏈接成功以後會返回一個socket對象,socket對象能夠建立輸入流InputStream接收客戶端發送的數據,也能夠建立輸出流OutputStream發送數據。

ServerSocket ss = new ServerSocket(8888);//指定服務端監聽端口
		
Socket client = ss.accept();//等待鏈接,創建與客戶端的鏈接
		
InputStream input = client.getInputStream();//使用輸入流來接收數據

byte[] buf = new byte[1024];
int length = input.read(buf);//等待客戶端發送數據

client.close();//關閉鏈接
ss.close();
複製代碼

使用TCP協議實現兩端雙向聊天功能:

一、新建TCP_Client客戶端類:

//TCP客戶端
public class TCP_Client {
	public static void main(String[] args) throws Exception {
		Socket s = new Socket("127.0.0.1", 8888);//與Server端創建鏈接
		
		OutputStream output = s.getOutputStream();//使用輸出流來發送數據
		InputStream input = s.getInputStream();//使用輸入流接收來自Server的數據
		
		/**
		 * 匿名內部類建立一個線程來接收數據
		 * */
		new Thread() {
			public void run() {
				byte[] buf = new byte[1024];//字節數組容器
				int length = -1;
				try {
					while ((length = input.read(buf))!=-1) {//等待服務端發送數據
						System.out.println(new String(buf, 0, length));
					}
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}.start();
		
		/**
		 * 發送數據
		 * */
		Scanner scanner = new Scanner(System.in);
		while (true) {
			String in_str = scanner.nextLine();
			if (in_str.equals("end"))break;
			output.write(in_str.getBytes());//向Server端寫入數據
		}
		
		s.close();//關閉鏈接
	}
}
複製代碼

一、新建TCP_Server服務端類:

//TCP鏈接的服務端
public class TCP_Server {
	public static void main(String[] args) throws Exception {
		ServerSocket ss = new ServerSocket(8888);//指定服務端監聽端口
		
		Socket client = ss.accept();//等待鏈接,創建與客戶端的鏈接
		System.out.println("客戶端已鏈接進來!");
		
		InputStream input = client.getInputStream();//使用輸入流來接收數據
		OutputStream output = client.getOutputStream();//使用輸出流發送數據
		
		/**
		 * 匿名內部類建立一個線程來發送數據
		 * */
		new Thread() {
			public void run() {
				Scanner scanner = new Scanner(System.in);
				while (true) {
					String str = scanner.nextLine();
					if (str.equals("end"))break;
					try {
						output.write(str.getBytes());//向客戶端寫入數據
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}.start();
		
		/**
		 * 接收數據
		 * */
		byte[] buf = new byte[1024];
		int length = -1;
		while ((length = input.read(buf))!=-1) {//等待客戶端發送數據
			System.out.println(new String(buf, 0, length));
		}
		
		client.close();//關閉與客戶端的鏈接
		ss.close();//關閉監聽
	}
}

複製代碼

運行結果:

客戶端:

客戶端

服務端:

服務端

多個客戶端發送數據,一個服務端接收數據:

一、新建TCP_Server_Many類,能夠接收多個客戶端鏈接的TCP服務端和處理多個客戶端的數據:

public class TCP_Server_Many {
	public static void main(String[] args) {
		new VerbClientConnect().start();//啓動服務端監聽線程監聽多個客戶端的鏈接
	}
}

//監聽多個客戶端的鏈接
class VerbClientConnect extends Thread {
	@Override
	public void run() {
		try {
			ServerSocket serverSocket = new ServerSocket(8888);
			int i=0; 
			while (true) {
				Socket socket = serverSocket.accept();//等待請求鏈接
				i++;
				System.out.println("接收到一個客戶端的鏈接:Client"+i+socket.getInetAddress());
				new ClientMessage(socket,i).start();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

//處理客戶端發送的消息
class ClientMessage extends Thread {
	
	private Socket socket;
	private int i;
	
	public ClientMessage(Socket socket, int i) {
		this.socket=socket;
		this.i=i;
	}

	@Override
	public void run() {
		try {
			InputStream input = socket.getInputStream();//使用輸入流來接收數據
			byte[] buf = new byte[1024];
			int length = -1;
			while ((length = input.read(buf))!=-1) {//等待客戶端發送數據
				System.out.println("來自客戶端Client"+i+"的消息:"+new String(buf, 0, length));
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (socket!=null) {
				try {
					socket.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}
複製代碼

二、新建TCP_Client_Many類,能夠發送多條數據的TCP客戶端:

public class TCP_Client_Many {
	public static void main(String[] args) throws Exception {
		Socket socket = new Socket("127.0.0.1", 8888);//請求鏈接
		OutputStream output = socket.getOutputStream();//使用輸出流來發送數據
		Scanner scanner = new Scanner(System.in);
		while (true) {
			String str = scanner.nextLine();
			if (str.equals("end"))break;
			output.write(str.getBytes());//向服務端發送數據
		}
		socket.close();
	}
}
複製代碼

運行效果:

Client1:

Client2:

Client3:

服務端:

今日寄語:

種一棵樹最好的時機是十年前,其次是如今!

歡迎關注我的微信公衆號:桃李報春

相關文章
相關標籤/搜索