Java_網絡編程_枚舉

1、什麼是ip地址
簡述:ip地址是網絡中計算機的唯一標識。
舉例:ipv4–>xx.xx.xx.xx xx是0-255之間的一個數字,4位10進制數
ipv6–>xx.xx.xx.xx.xx.xx -->6位16進制數

局域網ip(通常爲192.168.xx.xx),在局域網內,不可以重複
外網ip,在外網環境下不可以重複
【如家中連接的WiFi,移動聯通等通信公司給路由器分配一個外網ip,所有連接該wifi的設備被分配一個局域網ip,共用同一個外網ip。】

如何查看本機ip–>ipconfig

每個域名,訪問的其實都是某個服務器,服務器其實是一臺計算機。
訪問域名的時候,其實就是通過服務器的ip地址,找到服務器並獲取數據。
域名跟ip地址是一一對應的。【ping 域名 、ping ip地址】

特殊的ip地址,本地ip:
	127.0.0.1 localhost

2,在Java中處理IP地址。
InetAddress表示一個IP地址對象

	//可以根據主機名(計算機名(通過計算機-->屬性查看))構建InetAddress對象
	//也可以根據ip地址(字符串)構建InetAddress對象
	InetAddress ia = InetAddress.getByName(String name);
	System.out.println(ia);

3,端口號
我們的電腦上有很多運行的程序,有的程序不需要跟外界交互(單機軟件)
有的程序需要跟外界交互,這個時候我們需要通過端口號區分我們要跟那個軟件交互。
端口號默認系統分配,也可以有程序向系統申請某一端口號,
同理,局域網ip也由路由器默認分配,但也可向其申請某一局域網ip,
若申請的端口號或ip已被佔據,則申請者會遭到拒絕。

總結:通過ip定位計算機,通過port定位哪個軟件
注意:端口號是不能重複的。端口號是一個數字(0到6萬多)。
百度百科:https://baike.baidu.com/item/%E7%AB%AF%E5%8F%A3%E5%8F%B7/10883658
	可以通過 360流量防火牆-->網絡連接 查看各進程端口號		

查看進程端口號的方法
4,通信協議(兩個計算機通信遵循的規則)
通信規則:
UDP–>速度快、不需要建立連接、不可靠
TCP—>速度慢、需要通過三次握手建立連接、可靠
舉例:UDP:發短信 、、TCP:打電話

網絡編程的三要素總結:
IP地址,端口號,通信協議。
5,Socket套接字
在程序中我們通過Socket進行通信,在使用Socket通信的時候
需要指定上面編程的三要素(ip,port,協議)

數據發送分成兩步
第一步是監聽(等待數據發送過來),用來接收數據。需要指定監聽的是哪個端口號
第二步是發送,需要指定發送到哪個計算機(IP地址),需要指定發送到這個計算機的哪個端口號。

Socket中分爲發送端和接收端
6,使用UDP發送數據

DatagramSocket ds = new DatagramSocket();//負責發送
	
	//Scanner s = new Scanner(System.in);    //用於循環發送數據
	//while(true){                           //用於循環發送數據
	//String str = s.nextLine();             //用於循環發送數據
	//if(str.equals("end")) break;           //用於循環發送數據
	//創建要發送的信息
	byte[] buf = "udp傳送的信息".getBytes();     //用於循環發送數據是數據改爲str
	int length = buf.length;
	InetAddress address = InetAddress.getByName("localhost");//指定包裹的目的地地址
	int port = 50000; //一個當前不在運行的端口號
	//int port = 7874;  //指定包裹的目的地端口號
	
	//封裝數據的數據包
	DatagramPacket dp = new DatagramPacket(buf,length,address,port);
	
	ds.send(dp);//發送數據
	
	//}                                   //用於循環發送數據
	ds.close();//釋放資源

UDP只負責將數據發出去,不管是否有人收到。上述運行成功。
Socket都是要釋放資源的,所以常常將socket.close();用finally包裹,以確保資源釋放。
(如果不釋放資源,socket會一直等待去工作)

7、使用UDP接收數據:

DatagramSocket ds = new DatagramSocket(7874); //指定接收者要監聽的本機的某一端口號
	//再次啓動該語句,會由於該端口已被綁定(資源未釋放)而報異常
	
	byte[] buf = new byte[1024];
	int length = buf.length;
	
	//while(true){                   //用於持續接收數據
	//創建用來裝信息的包裹基本組成
	DatagramPacket dp = new DatagramPacket(buf, length);
	
	//使用包裹 dp 去裝載接收到的信息,receive後dp中還包含其他關於發送端的信息
	ds.receive(dp);
	
	//將接收到的信息組裝成String,length直接返回data的長度
	String s = new String(dp.getData(),0,dp.getLength());
	
	System.out.println(s);
	System.out.println(dp.getAddress());//獲取發送端的地址
	
	System.out.println(dp.getPort());//獲取發送端的端口號
	//發生端的端口號每次在發送信息時由系統自動分配,所以很有可能每次都不同
	//}                              //用於持續接收數據
	
	ds.close();       //當持續接收數據時,可不釋放資源(使其持續等待數據)

啓動時先啓動接收端,再啓動發送端。

8多線程與UDP結合實現雙向交流:
根據6,7的內容創建UDP_sendThread和UDP_receiveThread,爲聊天1號同時開啓發送線程和接收線程,爲聊天2號也start發送線程和接收線程,即可雙向交流。

9、同理,使用TCP完成持續發送與接收數據:

//使用tcp 發送端(client,客戶端)
	//與UDP的不同-->new Socket時會尋找服務器端以求建立連接
	Socket send = new Socket("localhost",7878);//發送到本地7878端口
	
	OutputStream out = send.getOutputStream();
	
	Scanner s = new Scanner(System.in);
	while(true) {
	String str = s.nextLine();
	if(str.equals("end")) break;
	
	out.write(str.getBytes());
	}
	
	send.close();

接收端:

	//接收端(server,服務器端)
	ServerSocket ss = new ServerSocket(7878);//監聽7878端口
	
	//程序在這裏停止,等待Socket建立連接,發送端new Socket("localhost",7878)時建立連接
	Socket receive = ss.accept();
	
	InputStream is = receive.getInputStream();
	byte[] bt = new byte[1024];
	
	int length =-1;
	
	/*這個輸入流要麼[管道中有數據-->接收數據],要麼處於[管道中沒數據-->等待狀態],
	   在之前學習的IO流的read方法是不會暫停(等待)的*/
	/*當客戶端close-->客戶端不再向管道中寫數據--->流結束-->輸入流的read會返回-1
	與UDP的不同--->服務器端知道客戶端的狀態*/
	while((length = is.read(bt))!=-1) {
		System.out.println(new String(bt,0,length));
	}
	
	//在得到客戶端關閉後,將服務器端進行關閉
	receive.close();
	ss.close();

10、使用TCP實現雙向交流
使用【多線程】以及【服務器端Socket與客戶端Socket都可獲得輸入流及輸出流】來使服務器端與客戶端 都 同時開啓接收和進行輸入 即可。(注意仍要先打開服務器端,再打開客戶端!)
11、使用TCP實現多客戶端向服務器端發信息
服務器端持續等待新的客戶端的接入,並在每次與客戶端接入後在服務器端創建一個新的對應的Socket,使通道連通【該通道建立於一個新的線程,用read來持續等待接收數據】。
12、枚舉類型【見名知意,增加代碼可讀性】

手動實現枚舉類型:

class SeasonDemo{
	static final int Spring = 0;
	static final int SUMMER = 1;
	static final int FALL = 2;
	static final int WINTER = 3;
}
-----------------------------------
通過Enum實現枚舉類型:

enum SeasonDemo {
//枚舉類型,默認數值從0開始+1遞增
Spring,SUMMER,FALL,WINTER
}

對枚舉類型的應用:

//枚舉類型的賦值
SeasonDemo sd1 = SeasonDemo.Spring;
SeasonDemo sd2 = SeasonDemo.WINTER;
	
System.out.println(sd1.name());//返回定義的name:Spring
System.out.println(sd2.ordinal());//返回對應的int值:3
System.out.println(sd1 == SeasonDemo.Spring);//true,Object數據的比較
	
//遍歷所有的SeasonDemo值
for(SeasonDemo s:SeasonDemo.values())
	System.out.println(s);
//返回Spring,SUMMER,FALL,WINTER
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章