天天看點

黑馬程式員 網絡(UDP傳輸和TCP傳輸)及反射一.IP位址

------<a href="http://www.itheima.com" target="_blank" rel="external nofollow" target="blank">Java教育訓練、Android教育訓練、iOS教育訓練、.Net教育訓練</a>、期待與您交流! -------

一.IP位址

每個裝置在網絡中的唯一辨別

    每台網絡終端在網絡中都有一個獨立的位址,我們在網絡中傳輸資料就是使用這個位址。

    ipconfig:檢視本機IP

    ping:測試連接配接

    本地回路位址:127.0.0.1255.255.255.255是廣播位址

    IPv4:4個位元組組成,4個0-255。大概42億,30億都在北美,亞洲4億。2011年初已經用盡。

    IPv6:8組,每組4個16進制數。

    1a2b:0000:aaaa:0000:0000:0000:aabb:1f2f

    1a2b::aaaa:0000:0000:0000:aabb:1f2f

    1a2b:0000:aaaa::aabb:1f2f

    1a2b:0000:aaaa::0000:aabb:1f2f

    1a2b:0000:aaaa:0000::aabb:1f2f

二.端口号

每個程式在裝置上的唯一辨別

    每個網絡程式都需要綁定一個端口号,傳輸資料的時候除了确定發到哪台機器上,還要明确發到哪個程式。

    端口号範圍從0-65535

    編寫網絡應用就需要綁定一個端口号,盡量使用1024以上的,1024以下的基本上都被系統程式占用了。

    常用端口

    mysql: 3306

    oracle: 1521

    web: 80

    tomcat: 8080

    QQ: 4000

    feiQ: 2425

三.網絡協定

為計算機網絡中進行資料交換而建立的規則、标準或約定的集合。

    UDP

    面向無連接配接,資料不安全,速度快。不區分用戶端與服務端。

    TCP

      面向連接配接(三次握手),資料安全,速度略低。分為用戶端和服務端。

    三次握手: 用戶端先向服務端發起請求, 服務端響應請求, 傳輸資料

四.Socket

通信的兩端都有Socket。

    網絡通信其實就是Socket間的通信。

    資料在兩個Socket間通過IO流傳輸。

    Socket在應用程式中建立,通過一種綁定機制與驅動程式建立關系,告訴自己所對應的IP和port。

五.UDP傳輸

    1.發送

    建立DatagramSocket, 随機端口号

    建立DatagramPacket, 指定資料, 長度, 位址, 端口

    使用DatagramSocket發送DatagramPacket

    關閉DatagramSocket

    2.接收

    建立DatagramSocket, 指定端口号

    建立DatagramPacket, 指定數組, 長度

    使用DatagramSocket接收DatagramPacket

    關閉DatagramSocket

    從DatagramPacket中擷取資料

    3.接收方擷取ip和端口号

    String ip =packet.getAddress().getHostAddress();

    int port = packet.getPort();

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Scanner;

public class Demo2_Send {

	/**
	 * 1.發送 建立DatagramSocket, 随機端口号 建立DatagramPacket, 指定資料, 長度, 位址, 端口
	 * 使用DatagramSocket發送DatagramPacket 關閉DatagramSocket
	 * 
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {
		// String str = "我讀書少,你不要騙我";
		DatagramSocket socket = new DatagramSocket(); // 建立Socket對象,相當于建立碼頭
		Scanner sc = new Scanner(System.in);
		while (true) {
			String line = sc.nextLine();
			if("quit".equals(line))
				break;
			DatagramPacket packet = // 建立Packet對象,相當于建立集裝箱
			new DatagramPacket(line.getBytes(), line.getBytes().length,InetAddress.getByName("127.0.0.1"), 6666);
			socket.send(packet); // 發送集裝箱
		}
		socket.close();
	}

}
           
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class Demo2_Receive {

	/**
	 * 2.接收
		建立DatagramSocket, 指定端口号
		建立DatagramPacket, 指定數組, 長度
		使用DatagramSocket接收DatagramPacket
		關閉DatagramSocket
		從DatagramPacket中擷取資料
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		DatagramSocket socket = new DatagramSocket(6666);	//建立Socket對象,相當于建立碼頭
		DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);//建立Packet對象,相當于建立集裝箱接貨
		while(true) {
			socket.receive(packet);											//接收資料
			byte[] arr = packet.getData();									//擷取資料
			int len = packet.getLength();									//擷取有效的位元組個數
			String ip = packet.getAddress().getHostAddress();		//擷取ip位址
			System.out.println(ip + ":" + new String(arr,0,len));
		}
	}

}
           

多線程

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Scanner;

public class Demo3_MoreThread {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new Receive().start();
		new Send().start();
	}

}

class Receive extends Thread {
	public void run() {
		try {
			DatagramSocket socket = new DatagramSocket(6666);	//建立Socket對象,相當于建立碼頭
			DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);//建立Packet對象,相當于建立集裝箱接貨
			while(true) {
				socket.receive(packet);											//接收資料
				byte[] arr = packet.getData();									//擷取資料
				int len = packet.getLength();									//擷取有效的位元組個數
				String ip = packet.getAddress().getHostAddress();		//擷取ip位址
				System.out.println(ip + ":" + new String(arr,0,len));
			}
		} catch (Exception e) {
			
			e.printStackTrace();
		} 
	}
}

class Send extends Thread {
	public void run() {
		try {
			DatagramSocket socket = new DatagramSocket(); // 建立Socket對象,相當于建立碼頭
			Scanner sc = new Scanner(System.in);
			while (true) {
				String line = sc.nextLine();
				if("quit".equals(line))
					break;
				DatagramPacket packet = // 建立Packet對象,相當于建立集裝箱
				new DatagramPacket(line.getBytes(), line.getBytes().length,InetAddress.getByName("192.168.33.186"), 6666);
				socket.send(packet); // 發送集裝箱
			}
			socket.close();
		} catch (Exception e) {
			
			e.printStackTrace();
		} 
	}
}
           

六.TCP傳輸

1.用戶端

       建立Socket連接配接服務端(指定ip位址,端口号)通過ip位址找對應的伺服器

       調用Socket的getInputStream()和getOutputStream()方法擷取和服務端相連的IO流

       輸入流可以讀取服務端輸出流寫出的資料

       輸出流可以寫出資料到服務端的輸入流

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class Demo2_Client {

	/**
	 *1.用戶端
		建立Socket連接配接服務端(指定ip位址,端口号)通過ip位址找對應的伺服器
		調用Socket的getInputStream()和getOutputStream()方法擷取和服務端相連的IO流
		輸入流可以讀取服務端輸出流寫出的資料
		輸出流可以寫出資料到服務端的輸入流
	 * @throws Exception 
	 * @throws UnknownHostException 
	 */
	public static void main(String[] args) throws Exception {
		Socket socket = new Socket("127.0.0.1", 12345);		//建立用戶端
		/*InputStream is = socket.getInputStream();			//擷取輸入流
		OutputStream os = socket.getOutputStream();			//擷取輸出流
		
		byte[] arr = new byte[1024];
		int len = is.read(arr);						//讀取伺服器發送的資料
		System.out.println(new String(arr,0,len));
		
		os.write("學習挖掘機哪家強".getBytes());			//将資料寫給伺服器
*/		
		BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));//包裝位元組輸入流
		//BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
		PrintStream ps = new PrintStream(socket.getOutputStream());//包裝位元組輸出流
		System.out.println(br.readLine());				//讀取伺服器寫過來的内容
		ps.println("我要報名就業班");						//将資料寫給伺服器
		System.out.println(br.readLine())
		ps.println("不學了");
		//bw.write("我要報名就業班");
		socket.close();
	}

}
           

2.服務端

       建立ServerSocket(需要指定端口号)

       調用ServerSocket的accept()方法接收一個用戶端請求,得到一個Socket

       調用Socket的getInputStream()和getOutputStream()方法擷取和用戶端相連的IO流

       輸入流可以讀取用戶端輸出流寫出的資料

       輸出流可以寫出資料到用戶端的輸入流

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Demo2_Server {

	/**
	 * 2.服務端
		建立ServerSocket(需要指定端口号)
		調用ServerSocket的accept()方法接收一個用戶端請求,得到一個Socket
		調用Socket的getInputStream()和getOutputStream()方法擷取和用戶端相連的IO流
		輸入流可以讀取用戶端輸出流寫出的資料
		輸出流可以寫出資料到用戶端的輸入流
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		ServerSocket server = new ServerSocket(54321);			//建立服務端,綁定54321端口
		Socket socket = server.accept();						//接受用戶端請求
		/*InputStream is = socket.getInputStream();				//擷取位元組輸入流
		OutputStream os = socket.getOutputStream();				//擷取位元組輸出流
		
		os.write("百度一下你就知道".getBytes());				//将内容寫給用戶端
		
		byte[] arr = new byte[1024];
		int len = is.read(arr);							//從用戶端讀取資料
		System.out.println(new String(arr,0,len));				*/
		BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));//包裝位元組輸入流
		//BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
		
		//bw.write("歡迎咨詢傳智播客");
		PrintStream ps = new PrintStream(socket.getOutputStream());//包裝位元組輸出流,因為裡面有一個println的方法
		ps.println("歡迎咨詢傳智播客");						//将字元串寫到用戶端
		System.out.println(br.readLine());				//讀取用戶端發過來的資訊
		ps.println("報滿了,等下一期吧");
		System.out.println(br.readLine());
		server.close();
		socket.close();
	}

}
           

建立多線程的服務端,可以不斷的向服務端通路

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Demo3_MoreThread {

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		ServerSocket server = new ServerSocket(12345);
		while(true) {
			final Socket socket = server.accept();			//不斷的接收用戶端的請求
			new Thread() {
				public void run() {
					try {
						BufferedReader br = 
						new BufferedReader(new InputStreamReader(socket.getInputStream()));
						PrintStream ps = new PrintStream(socket.getOutputStream());
						
						ps.println("歡迎咨詢黑馬程式員");
						System.out.println(br.readLine());
						ps.println("不一萬就業不給一分錢");
						System.out.println(br.readLine());
						ps.println("不學拉到");
						socket.close();
					} catch (Exception e) {
						
						e.printStackTrace();
					}
				}
			}.start();
		}
	}

}
           

七.反射

1.Class

       .class檔案加載到記憶體中就是一個Class對象

       擷取Class對象的方式有3種:

       Scanner sc = newScanner("xxx.txt");

           Class.forName(sc.nextLine());

           類名.class

           對象.getClass()

import cn.itcast.bean.Person;

public class Demo1_Reflect {

	/**
	 * @param args
	 * @throws ClassNotFoundException 
	 */
	public static void main(String[] args) throws ClassNotFoundException {
		Class<?> clazz1 = Class.forName("cn.itcast.bean.Person");
		Class<?> clazz2 = Person.class;
		
		Person p = new Person();
		Class<?> clazz3 = p.getClass();
		
		System.out.println(clazz1 == clazz2);
		System.out.println(clazz2 == clazz3);
	}

}
           

2.Constructor

       Class類的newInstance()方法是使用該類無參的構造函數建立對象, 如果一個類沒有無參的構造函數, 就不 能這樣建立了

       可以調用Class類的getConstructor(String.class,int.class)方法擷取一個指定的構造函數

       然後再調用Constructor類的newInstance("張三",20)方法建立對象

import java.lang.reflect.Constructor;

import cn.itcast.bean.Person;

public class Demo3_Constructor {

	/*
	  @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		Class<?> clazz = Class.forName("cn.itcast.bean.Person");
		/*Person p = (Person) clazz.newInstance();
		System.out.println(p);*/
		Constructor con = clazz.getConstructor(String.class,int.class);//擷取有參的構造函數
		Person p = (Person) con.newInstance("張三",23);					//建立對象
		System.out.println(p);											//列印對象
	}

}
           

3.Field

       Class.getField(String)方法可以擷取類中的指定字段(可見的), 如果是私有的可以用getDeclaedField("name")方法擷取

       通過set(obj, "李四")方法可以設定指定對象上該字段的值, 如果是私有的需要先調用setAccessible(true)設定通路權限

       用擷取的指定的字段調用get(obj)可以擷取指定對象中該字段的值

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

import cn.itcast.bean.Person;

public class Demo4_Field {

	
	
	public static void main(String[] args) throws Exception {
		Class<?> clazz = Class.forName("cn.itcast.bean.Person");
		Constructor con = clazz.getConstructor(String.class,int.class);//擷取有參的構造函數
		Person p = (Person) con.newInstance("張三",23);					//建立對象
		
		/*Field f = clazz.getField("name");
		System.out.println(f);*/
		Field f = clazz.getDeclaredField("name");						//暴力反射
		f.setAccessible(true);											//去除權限
		f.set(p, "李四");
		System.out.println(p);
	}
           

4.Method

       Class.getMethod(String, Class...) 和 Class.getDeclaredMethod(String, Class...)方法可以擷取類中 的指定方法

       調用invoke(Object,Object...)可以調用該方法

       Class.getMethod("eat")invoke(obj) Class.getMethod("eat",int.class) invoke(obj,10)

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

import cn.itcast.bean.Person;

public class Demo5_Method {

	/**
	 *4.Method
		Class.getMethod(String, Class...) 和 Class.getDeclaredMethod(String, Class...)方法可以擷取類中的指定方法
		調用invoke(Object, Object...)可以調用該方法
		Class.getMethod("eat") invoke(obj) Class.getMethod("eat",int.class) invoke(obj,10)
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		Class<?> clazz = Class.forName("cn.itcast.bean.Person");
		Constructor con = clazz.getConstructor(String.class,int.class);//擷取有參的構造函數
		Person p = (Person) con.newInstance("張三",23);					//建立對象
		
		Method m = clazz.getMethod("eat");
		m.invoke(p);
		
		Method m2 = clazz.getMethod("eat", int.class);
		m2.invoke(p, 10);
	}

}
           

繼續閱讀