1:網(wǎng)絡(luò)概述
? 1.1 網(wǎng)絡(luò)的發(fā)展Net
? 1964年泽本,美國(guó)人---> 阿帕網(wǎng)--->以太網(wǎng)Internet
? 1.2 網(wǎng)絡(luò)的通信協(xié)議
windows電腦,android手機(jī)雀监,Mac平板---》聯(lián)網(wǎng) ---->網(wǎng)絡(luò)協(xié)議(一個(gè)文檔:長(zhǎng)度,速率,格式)
--->根據(jù)文檔來寫了一段代碼(通信協(xié)議)
? 1.3 通信協(xié)議的分類
TCP/IP協(xié)議: 是一組協(xié)議
TCP:傳輸控制協(xié)議
IP :互聯(lián)網(wǎng)協(xié)議
? 1.4 TCP/IP的分層
應(yīng)用層:主要負(fù)責(zé)應(yīng)用程序的協(xié)議,用來產(chǎn)生和顯示數(shù)據(jù)
HTTP:超文本傳輸協(xié)議(http://www.baidu.com)
FTP :文件傳輸協(xié)議(ftp://192.168.10.82)
DNS : 域名解析: www.baidu.com ---> 192.168.10.82
傳輸層:主要使網(wǎng)絡(luò)程序進(jìn)行通信,保證輸出的可靠性
? ? TCP:傳輸控制協(xié)議
UDP:用戶數(shù)據(jù)報(bào)協(xié)議
網(wǎng)絡(luò)層:網(wǎng)絡(luò)層是整個(gè)TCP/IP協(xié)議的核心吟秩,找到對(duì)方的主機(jī)在哪里
IP :? 互聯(lián)網(wǎng)協(xié)議
ICMP:網(wǎng)際控制報(bào)文協(xié)議(ping? www.baidu.com)
鏈路層:鏈路層是用于定義物理傳輸通道,網(wǎng)卡和驅(qū)動(dòng),用于發(fā)送和接收數(shù)據(jù)
OSI模型:7層模型
1.5 IP地址和端口
要想和一臺(tái)主機(jī)建立聯(lián)系绽淘,必須知道對(duì)方主機(jī)的IP和端口
IP地址:
在一個(gè)網(wǎng)絡(luò)中涵防,IP地址作為一臺(tái)主機(jī)的唯一標(biāo)識(shí)
? ? IP的地址分類:
IPV4:
xxx.xxx.xxx.xxx :點(diǎn)分十進(jìn)制 ---->二進(jìn)制(110100101010)
使用4個(gè)字節(jié)來描述ip: 1.1.1.1 ---> 255.255.255.255 --->21億
? //網(wǎng)絡(luò)號(hào)? 主機(jī)號(hào)
A類:10.xxx.xxx.xxx? 國(guó)家級(jí)
255.0.0.0
B類:10.10.xxx.xxx? 企業(yè)級(jí)(百度)
255.255.0.0
C類:10.10.10.xxx
? ? 255.255.255.0
192.168.164.255? --->路由器 ---- 》電信網(wǎng)關(guān) ---->順義區(qū)192.168.103 --->xxx-?
10.10.10.1 :? 網(wǎng)關(guān)地址
10.10.10.255 :廣播地址
IPV6:
16個(gè)字節(jié) 128個(gè)二進(jìn)制位 2^128? ----》無限大
? 端口號(hào):
? ? 數(shù)據(jù)庫(kù):3306
ftp:? 21
標(biāo)識(shí)一臺(tái)電腦上唯一的一個(gè)進(jìn)程()
端口號(hào)是一個(gè)16位的數(shù)字(1-65535)
< 1024 系統(tǒng)使用的
? ? 1024 - 6000 :系統(tǒng)保留
? ? >6000 :自己使用
8888 9999 12306? 10086
ip地址和端口號(hào)就可以唯一的表示哪臺(tái)主機(jī)哪個(gè)進(jìn)程
3:InetAddress 類
用來描述電腦的ip和其他信息
//通過某種方式獲取InetAddress對(duì)象
public static InetAddress getByName(String host) //根據(jù)主機(jī)名或者網(wǎng)址獲取Ip
? ? //在一個(gè)局域網(wǎng)內(nèi)部沪铭,主機(jī)名和IP地址的作用是一樣的
public String getHostName()? ? //獲取主機(jī)名
public String getHostAddress() //獲取IP地址
public static InetAddress getLocalHost() //獲取本主機(jī)的ip和其他信息
例子:
public class Demo01InetAddress {
public static void main(String[] args) throws UnknownHostException {
// //通過某種方式獲取InetAddress對(duì)象
// public static InetAddress getByName(String host) //根據(jù)主機(jī)名或者網(wǎng)址獲取Ip
// //在一個(gè)局域網(wǎng)內(nèi)部壮池,主機(jī)名和IP地址的作用是一樣的
// public String getHostName() //獲取主機(jī)名
// public String getHostAddress() //獲取IP地址
//根據(jù)主機(jī)名獲取InetAddress對(duì)象 ---->獲取IP
// InetAddress address = InetAddress.getByName("LAPTOP-6F2V5QTF");
// //獲取IP
// String ip = address.getHostAddress();
// System.out.println(ip);
//根據(jù)網(wǎng)址獲取InetAddress對(duì)象 ---->獲取IP
InetAddress address2 = InetAddress.getByName("www.baidu.com");
//獲取IP
String ip2 = address2.getHostAddress();
System.out.println(ip2);
//將一個(gè)IP字符串轉(zhuǎn)為Inetaddress對(duì)象
InetAddress ip3 = InetAddress.getByName("192.168.164.67");
//public static InetAddress getLocalHost() //獲取本主機(jī)的ip和其他信息
InetAddress ip4 = InetAddress.getLocalHost();
//獲取本電腦的主機(jī)名
String hostName = ip4.getHostName();
String ip = ip4.getHostAddress();
System.out.println("主機(jī)名:" + hostName);
System.out.println("ip:" + ip);
}
}
4:UDP協(xié)議
UDP是一種面向無連接的協(xié)議
UDP的通信雙方在傳輸數(shù)據(jù)之前不需要建立連接,發(fā)送端只管發(fā)杀怠,根本不會(huì)關(guān)心接收端是否接收
優(yōu)點(diǎn): 傳輸速度快椰憋,效率高,實(shí)時(shí)性強(qiáng)
缺點(diǎn): 數(shù)據(jù)容易丟失赔退,不安全
應(yīng)用場(chǎng)景:直播橙依,視頻會(huì)議证舟,
5:TCP協(xié)議
TCP是一種面向連接的協(xié)議:
TCP的雙方在通信之前,必須先要建立連接窗骑,這個(gè)連接被稱為三次握手
優(yōu)點(diǎn):可以保證數(shù)據(jù)傳輸?shù)目煽啃耘穑瑪?shù)據(jù)無丟失,數(shù)據(jù)可以超時(shí)重傳
缺點(diǎn): 傳輸速度慢创译,效率低
應(yīng)用場(chǎng)景: 對(duì)數(shù)據(jù)的傳輸質(zhì)量要求高:金融系統(tǒng)抵知,終端支付,密碼管理
6: UDP編程
//發(fā)送端
public class Demo01Send {
//1.創(chuàng)建DatagramSockt對(duì)象,造一個(gè)碼頭
DatagramSocket ds = new DatagramSocket();
//2.準(zhǔn)備要發(fā)送的數(shù)據(jù)
byte[] data = "hello".getBytes();
//3.將你要發(fā)送的數(shù)據(jù)方法在包中
/*
參數(shù)1:表示要發(fā)送的數(shù)據(jù)
參數(shù)2:表示發(fā)送數(shù)據(jù)的長(zhǎng)度
參數(shù)3:表示接收端的IP
參數(shù)4:表示接受的端口
*/
//將IP字符串轉(zhuǎn)換為InetAddress對(duì)象
InetAddress address = InetAddress.getByName("192.168.164.67");
DatagramPacket dp = new DatagramPacket(data, data.length,address,9999(port)
//4:發(fā)送數(shù)據(jù)
ds.send(dp);
//5.關(guān)閉資源
ds.close();
/*
第5章總結(jié)
5.1知識(shí)點(diǎn)總結(jié)
?IP地址:用來唯一表示我們自己的電腦的,是一個(gè)網(wǎng)絡(luò)標(biāo)示
?端口號(hào): 用來區(qū)別當(dāng)前電腦中的應(yīng)用程序的
?UDP: 傳送速度快软族,但是容易丟數(shù)據(jù)刷喜,如視頻聊天,語音聊天
?TCP: 傳送穩(wěn)定互订,不會(huì)丟失數(shù)據(jù)吱肌,如文件的上傳、下載
?UDP程序交互的流程
?發(fā)送端
1,創(chuàng)建DatagramSocket對(duì)象
2仰禽,創(chuàng)建DatagramPacket對(duì)象氮墨,并封裝數(shù)據(jù)
3,發(fā)送數(shù)據(jù)
4吐葵,釋放流資源
?接收端
1,創(chuàng)建DatagramSocket對(duì)象
2,創(chuàng)建DatagramPacket對(duì)象
3,接收數(shù)據(jù)存儲(chǔ)到DatagramPacket對(duì)象中
4,獲取DatagramPacket對(duì)象的內(nèi)容
5,釋放流資源
?TCP程序交互的流程
?客戶端
1,創(chuàng)建客戶端的Socket對(duì)象
2,獲取Socket的輸出流對(duì)象
3,寫數(shù)據(jù)給服務(wù)器
4,獲取Socket的輸入流對(duì)象
5规揪,使用輸入流,讀反饋信息
6,關(guān)閉流資源
?服務(wù)器端
1温峭,創(chuàng)建服務(wù)器端ServerSocket對(duì)象猛铅,指定服務(wù)器端端口號(hào)
2,開啟服務(wù)器凤藏,等待著客戶端Socket對(duì)象的連接奸忽,如有客戶端連接,返回客戶端的Socket對(duì)象
3,通過客戶端的Socket對(duì)象揖庄,獲取客戶端的輸入流栗菜,為了實(shí)現(xiàn)獲取客戶端發(fā)來的數(shù)據(jù)
4,通過客戶端的輸入流,獲取流中的數(shù)據(jù)
5,通過客戶端的Socket對(duì)象蹄梢,獲取客戶端的輸出流疙筹,為了實(shí)現(xiàn)給客戶端反饋信息
6,通過客戶端的輸出流,寫數(shù)據(jù)到流中
7,關(guān)閉流資源
*/
/*
}
//接收端
public class Demo02Receive {
public static void main(String[] args) throws IOException {
//1:創(chuàng)建DatagramSocke對(duì)象,并指定端口號(hào)
DatagramPacket dp = new DatagramPacket(8888);
//2.創(chuàng)建DataramPacket對(duì)象指定要接收數(shù)據(jù)的位置和長(zhǎng)度
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes,bytes.length);
System.out.println("接收端在運(yùn)行")
//3.接收數(shù)據(jù)
//當(dāng)沒有數(shù)據(jù)發(fā)送過來則呈現(xiàn)阻塞.
ds.receive(dp);
//4.獲取接收到的數(shù)據(jù)
byte[] data = dp.getData();
//獲取接收數(shù)據(jù)的長(zhǎng)度
int len = dp.getLength();
//獲取發(fā)送端的IP
String ip = dp.getAddress().getHostAddress();
System.out.println("ip" + ip + "數(shù)據(jù):" + new String(data,0,data.length);
//關(guān)閉ziyuan
ds.close();
}
}
public class Demo01Send {
public static void main(String[] args) throws IOException {
//1.創(chuàng)建DatagrameSocket對(duì)象,造一個(gè)碼頭
DatagramSocket ds = new DatagramSocket();
Scanne sc = new Scanner(System.in);
while(true) {
//2.裝備要發(fā)送的數(shù)據(jù)
System.ou.println("請(qǐng)輸入你要發(fā)送的數(shù)據(jù)(exit退出)");
Stringstr= sc.nextLine();
byte[] data? = str.getBytes();
//3.將你要發(fā)送的數(shù)據(jù)放在包中
/*
參1:表示要發(fā)送的數(shù)據(jù)
參2:表示發(fā)送數(shù)據(jù)長(zhǎng)度
參3:表示接收端的IP
參4:表示接收端的端口
*/
//將IP字符串轉(zhuǎn)為InetAddress對(duì)象
InetAddress address = InetAddress.getByName("192.168.164.21");
DatagramPacket dp = new DatagramPacket(data, data.length,address,8888);
//4.發(fā)送數(shù)據(jù)
ds.send(dp);
if(str.equals("exit")) {
break;
}
}
//5.關(guān)閉資源
ds.close();
}
}
//UDPde 增強(qiáng)版 接收端
public class Demo02Receive {
public static void main(String[] args) throws IOException {
//1.創(chuàng)建DatagramSocket對(duì)象,并指定端口號(hào)
DatagramSocket ds = new DatagramSocket(8888);
//2.創(chuàng)建DatagramPacket對(duì)象,指定要接收的位置和長(zhǎng)度
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes,bytes.length)
System.out.println("接收端正在運(yùn)行");
while(true) {
//3.接收數(shù)據(jù)//當(dāng)沒有數(shù)據(jù)發(fā)送過來則程序組阻塞
ds.receive(dp);
//4.獲取接收到的數(shù)據(jù)
byte[] data = dp.getData()
//獲取接收數(shù)據(jù)的長(zhǎng)度i
int len = dp.getLength();
//獲取發(fā)送端的IP
String ip= dp.getAddress().getHoostAdress();
String str= new String(data,9,len);
if(str.equals("exit")) {
break;
}
//將獲取的數(shù)據(jù)轉(zhuǎn)為字符串
System.out.println("ip" + ip + "數(shù)據(jù):" + str)
}
//5:關(guān)閉資源
ds.close();
}
}
運(yùn)行: 先運(yùn)行接收端禁炒,再運(yùn)行發(fā)送端
7:TCP編程
//客戶端
public class ClientDemo {
public static void main(String[] args) throws Exception {
//創(chuàng)建Socket套接子
Socket socket = new Socket("192.168.164.21",9999);
//程序執(zhí)行到這里,客戶端和服務(wù)器已經(jīng)建立好了連接
//2.客戶端要給服務(wù)器發(fā)送數(shù)據(jù)
//2.1獲取輸出流
OutputStream os = socket.getOutputStream();
2.2發(fā)送數(shù)據(jù)
os.write("hello".getBytes());
//3.釋放資源
os.close();
socket.close();
}
}
//服務(wù)器
public class ServerDemo {
public static void main (String[] args) {
//創(chuàng)建ServerSocket對(duì)象,并指定端口號(hào)
ServerSocket server = new ServerSocket(9999);
//接收客戶端的請(qǐng)求
//已經(jīng)建立好連接
//通過socket可以獲取一切信息
System.out.println("服務(wù)器正在等待連接.......");
Socket socket = server.accept();
//3.服務(wù)器讀取數(shù)據(jù)
//3.1服務(wù)器獲取輸入流
InputStream is = cSocket.getInputStream();
//3.2讀取數(shù)據(jù)
byte[] bytes= new byte[1024];
int len = is.read(bytes);
//3.3將讀取的數(shù)據(jù)轉(zhuǎn)為字符串
System.out.println("讀取數(shù)據(jù):" + new String(bytes,0,len));
//4.釋放資源
is.close();
socket.close();
server.close();
}
}
//客戶端讀取圖片
public class ClientDemo {
public static void main(String[] args) throws Exception{
//1:創(chuàng)建Socket對(duì)象
Socket socket = new Socket("192.168.164.67",10086);
//2:獲取文件的輸入流
BufferedInoutStream bis = new BufferedInputStream(new FileInputStream("下載.jpg");
//4.從文件的輸入流中讀取數(shù)據(jù)并寫入套接子的輸出流
byte[] bytes = new byte[1024];
int len;
while((len = bis.read(bytes) != -1) {
os.write(bytes, 0 ,len);
}
//5.關(guān)閉資源
bis.close();
socket.close();
}
//服務(wù)器
public class ServerDemo {
public static void main(String[] args) throws IOException {
//1.創(chuàng)建ServerSocket對(duì)象
ServerSocket server = new ServerSocket(10086);
//2.接收請(qǐng)求
Socket socket = server.accpet();
//3.獲取文件的輸出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("liutao.jpg"));
//4.獲取套接子的輸入流
InputStream is = socket.getInputStream();
//5.將從套接子輸入流讀取的數(shù)據(jù)寫入文件的輸出流
byte[] bytes = new byte[1024];
ine len;
while((len = is.read(bytes)) != -1) {
bos.write(bytes, 0 , len);
//刷新后可以再
bos.flush();
}
//6.關(guān)閉資源
bos.close()
server.close();
socke.class();
}
}
//客戶端上傳圖片優(yōu)化
public class ClientDemo {
public static void main(String[] args) throws Exception {
//1.創(chuàng)建Socket對(duì)象
ocket socket = new Socket("192.168.164.21",1008);
//2.獲取文件的輸入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("劉濤.jpg");
//3.獲取套接字的輸出流
OutputStream os = socket.getOutputStream();
//4.從文件的輸入流中讀取數(shù)據(jù)并寫入套接子的輸出流
byte[] bytes = new byte[1024];
int len;
while((len = bis.read(bytes)) != -1) {
ow.write(bytes,0,len);
}
//客戶端需要關(guān)閉輸出流
socket.showdownOutput();
//接收服務(wù)器的反饋信息
//1.獲取套接字的輸入流
InputStream is = socket.getInputStream;
//2.讀取數(shù)據(jù)
len = is.read(bytes);
System.out.println(new String(bytes,0,len));
//5.關(guān)閉資源
bis.close();
socket.close();
}
}
//服務(wù)器(加上反饋信息的圖片上傳)
public class ServerDemo {
public static void main(String[] args) throws Exception {
//1.創(chuàng)建ServerSocket對(duì)象
ServerSocket server = new ServerSocket(10086);
System.out.println("accept之前");
//2.接收請(qǐng)求
Socket socket = socket.accept();
System.out.println("accept之后");
//3.獲取文件的輸出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("liutao.jpg"));
//4.獲取文件的輸出流
InputStream is =? socket.getInputStream();
//5.將套接子輸入流讀取的數(shù)據(jù)寫入文件的輸出流
byte[] bytes = new byte[1024];
int len;
System.out.println("while 之前");
/*
while循環(huán)沒有結(jié)束,說明read并沒有讀取到-1
現(xiàn)在是從套接子的輸入流讀取,讀取到-1條件是對(duì)方把輸出流給關(guān)閉了
關(guān)閉之后,說明客戶已經(jīng)沒有數(shù)據(jù)要給服務(wù)器發(fā)送了,這就讀取到-1
*/
while((len = is.read(bytes)) != -1) {
bos.write(bytes,0,len);
//刷新
bos.flush();
}
System.out.println("while? 之后");
//給客戶反饋信息
//獲取套接子輸出流
OutputStream os = socket.getOutputS();
//把信息發(fā)送給客戶端
os.write("文件上傳成功".getBytes);
//6.關(guān)閉資源
bos.cloas();
server.cloase();
}
}
//客戶端向服務(wù)器傳送圖片
public class ClientDemo {
public static void main(String[] args) throws Exception {
//1.創(chuàng)建Socket對(duì)象
Socket socket = new Socket("192.168.164.21",7799);
//獲取文件輸入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("劉濤.jpg"));
//獲取文件輸出流
OutputStream os = socket.getOutputStream();
byte[] bytes = new byte[1024];
int len;
while((lne = bis.read(bytes)) != -1) {
os.write(bytes,0,len);
//刷新
os.flush()
}
//關(guān)閉用戶端的輸出流
socket.showdownOutput();
//接收服務(wù)器反饋的信息
InputStream is = socket.getInputStream();
len = is.read(bytes);
System.out.peintln(new String(bytes,0,len));
bis.close();
socket.close();
}
}
//服務(wù)器用多線程執(zhí)行并接收的圖片進(jìn)行不同名的處理
public class ServerDemo {
public static void main(String[] args) throws Exception {
ServerSokcet server = new ServerSokcet();
while(true) {
Socket socket = server.accept();
new Thread(new MyRunnable(socket)).start();
}
}
}
public class MyRunnable implements Runnable {
Socket socket;
public MyRunnable() {}
public MyRunnable(Socket socket) {
this.socket = socket;
}
public void run () {
//處理意見建立好的連接
//上傳文件的代碼
BufferedOutputStream bos = null;
try {
//1.獲取套接子的輸入流
InputStream is = socket.getInputStream();
String fileName = "D:\\Server\\" + "副本" + System.currentTimeMillis() + ".jpg";
//2.獲取文件的輸出流
bos = new BufferedOutputStream(new FileOutputStream(fileName));
byte[] bytes = new byte[1024];
ine len;
while((len = is.read(bytes)) != -1) {
bos.write(bytes,0,len);
//刷新
bos.flush();
}
//給客戶端反饋信息
OutputStream os = socket.getOutputStream();
os.write("文件上傳成功".getBytes());
} catch (Exception e) {
e.printStackeTrace();
} finally {
try {
bos.close();
} catch (Exception o1) {
e1.printSackTrace();
}
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//客戶端和服務(wù)器進(jìn)行相互聊天(兩個(gè)人聊天)
//客戶端
public class Client {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("192.168.164.21",8888);
//創(chuàng)建讀取線程
Thread tRead = new Thread(new ReadThread(socket));
Thread tWrite = new Thread(new WriteThread(socket));
tRead.start();
tWrite.start();
}
}
public class Server {
public static void main(String[] args) throws Exception {
ServerSocket server = new ServerSokcet(8888);
Socket socket = server.accept();
//創(chuàng)建讀取線程
Thread tRead = new Thread(new ReadThread(socket));
Thread tWrite = new Thread(new WriteThread(socket));
tRead.start();
tWrite.start();
}
}
public class ReadThread implements Runnable {
Socket socket;
public ReadThread() {
super();
}
public ReadThread(Socket socket) {
super();
this.socket = socket;
}
public void run () {
try {
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
ine len;
while(true) {
len = is.read(bytes);
String ip = socket.getInetAddress().getHostAddress();
System.out.println("讀取數(shù)據(jù):" + new String(bytes,0,len));
}
}catch (Exception e) {
e.printStackTrace();
}
}
}
public class WriteThread implements Runnable {
Socket socket;
public WriteThread() {
super();
}
public WriteThread(Socket sokcet) {
super();
this.socket = socket;
}
public void run () {
Scanner sc = new Scanner(System.in);
//寫數(shù)據(jù)
try {
OutputStream os = socket.getOutputStream();
while(true) {
System.out.println("請(qǐng)輸入要發(fā)送的數(shù)據(jù):");
String str = sc.nextLine();
os.write(str.getBytes());
}
}catch (Exception e) {
e.printStackTrace();
}
}
}
//類的序列號(hào)(客戶端)
//學(xué)生類
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
public Student() {
super();
}
public Student(String name;int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//客戶端
public class Client {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("192.168.164.67",8888);
Student stu = new Student("劉濤",35);
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(stu);
}
}
//服務(wù)器
public class Server {
public static void main(String[] args) {
ServerSocket server = new ServerSocket(8888);
Socket socket = server.accept();
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
Student stu = (Student)ois.readObject();
System.out.println(stu.getName() + "\t" + stu.getAge());
}
}
//文件上傳? 服務(wù)器端
public class TCPServer {
public static void main(String[] args) {
//1.創(chuàng)建服務(wù)器,等待客戶端連接
ServerSocket server = new ServerSocket();
//2.實(shí)現(xiàn)多個(gè)客戶端連接服務(wù)器的操作
while(true) {
final Socket socket = server.accept();
//啟動(dòng)線程,完成與當(dāng)前客戶端的數(shù)據(jù)交互過程
new Thread() {
public void run() {
try {
//顯示那個(gè)客戶端Socket連接上了服務(wù)器
//得到IP地址對(duì)象
InetAddress ipObject = InetAddress.getInetAddress();
//得到ip地址字符串
String ip = ipObject.getHostAddress();
System.out.println("連接的ip是:" + ip);
//7.獲取Socket的輸入流
InputStream in = socket.getInputStream();
//8.創(chuàng)建目的地的字節(jié)輸出流(D:\\upload\\192.168.74.58(1).jpg
BufferedOutputStream fileOut = new BufferedOutputStream(new FileOutputStream("D:\\upload\\" + ip + "(" + System.currenTimeMillis() + ").jpg"));
//9.把Socket輸入流中的數(shù)據(jù),寫入目的地的字節(jié)輸出流中
byte[] buffer = new byte[1024];
int len = -1;
while((len = in.read(buffer)) != -1) {
//寫入目的地的字節(jié)輸出流中
fileOut.write(buffer,0,len);
}
//--反饋信息--
//10.獲取Socket的輸出流,作用:寫反饋信息給客戶端
OutputStream out = socket.getOutputStream();
//11.寫反饋信息給客戶端
out.wirte("圖片上傳成功".getBytes);
out.close();
fileout.cloas();
in.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
//server.cloae();
}
}
//上傳文件? 客戶端
public void shutdownOutput() 禁用此Socket的輸出流,間接的相當(dāng)于告知了服務(wù)器數(shù)據(jù)寫入完畢
public class TCPClient {
public static void main(String[] args) throws Exception {
//2.創(chuàng)建客戶端Socket,連接服務(wù)器
Socket socket = new Socket("192.168.164.21",8888);
//3.獲取Socket 流中的輸出流,功能:用來把數(shù)據(jù)寫到服務(wù)器
outputStream out = socket.getOutputStream();
//4.創(chuàng)建字節(jié)輸入流,功能:用來讀取數(shù)據(jù)源(圖片)的字節(jié)
BufferedInputStream fileIn = new BufferedInputStream(new FileInputStream("D:\\NoDir\\test.jpg"));
//5.把圖片數(shù)據(jù)寫到Socket的輸出流中(把數(shù)據(jù)傳到服務(wù)器)
byte[] buffer = new byte[1024];
int len = -1;
while((len = fileln.read(buffer)) != -1) {
//把輸入寫到Socket的輸出流中
out.write(buffer,0,len);
}
//6.客戶端發(fā)送數(shù)據(jù)完畢,結(jié)束Socket輸出流的寫入操作,告知服務(wù)器
socket.shutdownOutput();
//--反饋信息--
//12.獲取Socket的輸入流? ? 作用:讀反饋信息
InputStream in = socket.getInputStream();
//13.讀反饋信息
byte[] info = new byte[1024];
//把反饋信息存儲(chǔ)到info數(shù)組中,并記錄字節(jié)個(gè)數(shù)
int length = in.read(info);
//顯示反饋結(jié)果
System.out.println(new String(info,0,len));
//關(guān)閉流
in.close();
fileIn.close();
out.close();
socket.close();
}
}
?IP地址:用來唯一表示我們自己的電腦的而咆,是一個(gè)網(wǎng)絡(luò)標(biāo)示
?端口號(hào): 用來區(qū)別當(dāng)前電腦中的應(yīng)用程序的
?UDP: 傳送速度快,但是容易丟數(shù)據(jù)幕袱,如視頻聊天暴备,語音聊天
?TCP: 傳送穩(wěn)定,不會(huì)丟失數(shù)據(jù)们豌,如文件的上傳馍驯、下載
?UDP程序交互的流程
?發(fā)送端
1,創(chuàng)建DatagramSocket對(duì)象
2阁危,創(chuàng)建DatagramPacket對(duì)象,并封裝數(shù)據(jù)
3汰瘫,發(fā)送數(shù)據(jù)
4,釋放流資源
?接收端
1,創(chuàng)建DatagramSocket對(duì)象
2,創(chuàng)建DatagramPacket對(duì)象
3,接收數(shù)據(jù)存儲(chǔ)到DatagramPacket對(duì)象中
4,獲取DatagramPacket對(duì)象的內(nèi)容
5,釋放流資源
?TCP程序交互的流程
?客戶端
1,創(chuàng)建客戶端的Socket對(duì)象
2,獲取Socket的輸出流對(duì)象
3,寫數(shù)據(jù)給服務(wù)器
4,獲取Socket的輸入流對(duì)象
5擂煞,使用輸入流混弥,讀反饋信息
6,關(guān)閉流資源
?服務(wù)器端
1,創(chuàng)建服務(wù)器端ServerSocket對(duì)象对省,指定服務(wù)器端端口號(hào)
2蝗拿,開啟服務(wù)器,等待著客戶端Socket對(duì)象的連接蒿涎,如有客戶端連接哀托,返回客戶端的Socket對(duì)象
3,通過客戶端的Socket對(duì)象,獲取客戶端的輸入流劳秋,為了實(shí)現(xiàn)獲取客戶端發(fā)來的數(shù)據(jù)
4,通過客戶端的輸入流仓手,獲取流中的數(shù)據(jù)
5,通過客戶端的Socket對(duì)象,獲取客戶端的輸出流玻淑,為了實(shí)現(xiàn)給客戶端反饋信息
6,通過客戶端的輸出流嗽冒,寫數(shù)據(jù)到流中
7,關(guān)閉流資源
反射:
1:類的加載
當(dāng)我們第一次使用一個(gè)類,系統(tǒng)會(huì)做兩件事情:
1:將該類的字節(jié)碼文件(.class)文件加載到內(nèi)存
? ? 2: 系統(tǒng)還會(huì)為該字節(jié)碼文件創(chuàng)建一個(gè)對(duì)象:Class對(duì)象
a.txt? hello.java? D://lesson//a.txt ---->FIle類
a.class Hello.class Demo.class ---->Class類
? 2:一個(gè)類什么時(shí)候被加載
1. 創(chuàng)建類的實(shí)例
2. 類的靜態(tài)變量补履,或者為靜態(tài)變量賦值
3. 類的靜態(tài)方法
4. 使用反射方式來強(qiáng)制創(chuàng)建某個(gè)類或接口對(duì)應(yīng)的java.lang.Class對(duì)象
5. 初始化某個(gè)類的子類
6. 直接使用java.exe命令來運(yùn)行某個(gè)主類
3:反射的作用
? 1:反射可以讓我們?cè)诰幾g的時(shí)候使用一個(gè)不存在的或者以后才能存在類
? 2:反射可以訪問一個(gè)類的私有成員 MD5算法
? 3: 通過反射添坊,我們寫一些通用代碼
4:反射的步驟
1:獲取類的Class對(duì)象 //一個(gè)類在內(nèi)存中只有一個(gè)Class對(duì)象
2:通過Class對(duì)象獲取類的成員(構(gòu)造方法,成員變量箫锤,成員方法)
3:訪問這些變量和方法
package pack01_reflect;
import java.util.Scanner;
public class Demo01GetClass {
public static void main(String[] args) throws ClassNotFoundException {
//獲取一個(gè)類的Class對(duì)象
//1:通過類名來獲取Class對(duì)象
Class<?> clazz1 = Student.class;
//2: 通過類的對(duì)象獲取
Student stu = new Student();
Class<?> clazz2 = stu.getClass();
//一個(gè)類在內(nèi)存中只有一個(gè)Class對(duì)象
System.out.println(clazz1 == clazz2);
//3:通過類的全名來獲取
Class<?> clazz3 = Class.forName("pack01_reflect.Student");
}
}
? 單詞:
Class類
? Constructor 構(gòu)造
? Method 方法
? Field 字段
? instance 實(shí)例
? invoke 執(zhí)行
5:通過Class獲取類的成員
? ? 1:獲取類的構(gòu)造方法
? a:獲取所有的構(gòu)造
public Constructor<?>[] getConstructors() //只能獲取public修飾的構(gòu)造
public Constructor<?>[] getDeclaredConstructors() //可以獲取所有的構(gòu)造(包括私有)
package pack02_reflect;
import java.lang.reflect.Constructor;
public class Demo01GetConstructor {
public static void main(String[] args) throws ClassNotFoundException {
//1:獲取類的Class對(duì)象
Class<?> clazz = Class.forName("pack02_reflect.Student");
//2:獲取類中所有的構(gòu)造方法
// public Constructor<?>[] getConstructors() //只能獲取public修飾的構(gòu)造
// public Constructor<?>[] getDeclaredConstructors() //可以獲取所有的構(gòu)造(包括私有)
// Constructor<?>[] constructors = clazz.getConstructors();
// for (Constructor<?> constructor : constructors) {
// System.out.println(constructor);
// }
//構(gòu)造方法的獲取順序和方法的定義順序不一定一致
Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
for (Constructor<?> constructor : declaredConstructors) {
System.out.println(constructor);
}
}
}
? b:獲取單個(gè)的構(gòu)造
public Constructor<T> getConstructor(Class<?>... parameterTypes)
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
package pack02_reflect;
import java.lang.reflect.Constructor;
public class Demo02GetConstructor {
public static void main(String[] args) throws Exception{
//1:獲取類的Class對(duì)象
Class<?> clazz = Class.forName("pack02_reflect.Student");
//2:獲取單個(gè)的構(gòu)造(無參構(gòu)造)
Constructor<?> constructor = clazz.getConstructor();
//3:通過獲取的構(gòu)造來創(chuàng)建對(duì)象
Object obj = constructor.newInstance();
//4:通過對(duì)象調(diào)用方法
Student stu = (Student)obj;
stu.study();
System.out.println("-------------------------------");
//獲取類的有參構(gòu)造
Constructor<?> constructor2 = clazz.getConstructor(String.class, int.class);
//通過構(gòu)造創(chuàng)建對(duì)象:給方法傳實(shí)際的參數(shù)
Object obj2 = constructor2.newInstance("劉濤", 35);
System.out.println("----------------------------");
}
}
package pack02_reflect;
import java.lang.reflect.Constructor;
public class Demo03GetConstructor {
public static void main(String[] args) throws Exception{
//通過無參構(gòu)造創(chuàng)建對(duì)象的簡(jiǎn)化寫法
//1:獲取類的Class對(duì)象
Class<?> clazz = Class.forName("pack02_reflect.Student");
//2:獲取單個(gè)的構(gòu)造(無參構(gòu)造)
// Constructor<?> constructor = clazz.getConstructor();
//3:通過獲取的構(gòu)造來創(chuàng)建對(duì)象
// Object obj = constructor.newInstance();
Object obj = clazz.newInstance();
//4:通過對(duì)象調(diào)用方法
Student stu = (Student)obj;
stu.study();
}
}
? ? 2:獲取成員方法
? a:獲取所有的成員方法
public Method[] getMethods()
public Method[] getDeclaredMethods()
import java.lang.reflect.Method;
public class Demo01GetMethod {
public static void main(String[] args) throws ClassNotFoundException {
//1:獲取類的Class對(duì)象
Class<?> clazz = Class.forName("pack02_reflect.Student");
//2:獲取所有的方法
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println(method.getReturnType()+" "+method.getName());
}
}
}
? b:獲取單個(gè)的成員方法
public Method getMethod(String name,? ? Class<?>... parameterTypes)
public Method getDeclaredMethod(String name,? ? Class<?>... parameterTypes)
package pack03_reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Demo03GetMethod {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
//1:獲取類的Class對(duì)象
Class<?> clazz = Class.forName("pack03_reflect.Student");
Object obj = clazz.newInstance();
//2: 獲取有參數(shù)的構(gòu)造
/*
* 參1: 表示方法的名字
* 參2:方法形參類型的Class對(duì)象
*/
Method method = clazz.getMethod("add", int.class,int.class);
//3:調(diào)用方法
Object result = method.invoke(obj, 10,20);
int sum = (Integer)result;
System.out.println("sum = " + sum);
}
}
? ? 4:獲取成員變量
? a:獲取所有的成員變量
public Field[] getFields()
? ? public Field[] getDeclaredFields()
package pack04_reflect;
import java.lang.reflect.Field;
public class Demo01GetField {
public static void main(String[] args) throws Exception{
//1:創(chuàng)建Class對(duì)象
Class<?> clazz = Class.forName("pack04_reflect.Student");
Object obj = clazz.newInstance();
//2:獲取成員變量
//參數(shù):變量的名字
Field field1 = clazz.getDeclaredField("name");
Field field2 = clazz.getDeclaredField("age");
//給變量設(shè)置暴力訪問
field1.setAccessible(true);
field2.setAccessible(true);
//3:給變量賦值
//將obj對(duì)象的name變量賦值為柳巖
field1.set(obj, "柳巖");
field2.set(obj, 35);
//獲取obj的name變量的值
String name = (String)field1.get(obj);
//獲取obj的age變量的值
int age = (Integer)field2.get(obj);
// Student stu = (Student)obj;
// System.out.println(stu.getName() + " "+ stu.getAge());
}
}
? b:獲取單個(gè)成員變量
public Field getField(String name)
public Field getDeclaredField(String name)
//1:獲取類的Class對(duì)象
Class<?> clazz = Class.forName("pack02_reflect.Student");
//創(chuàng)建對(duì)象
Object obj = clazz.newInstance();
//2: 獲取單個(gè)的成員方法
Method method = clazz.getMethod("study");
//3:調(diào)用獲取的方法
//參1:表示這個(gè)方法由哪個(gè)對(duì)象來調(diào)用
method.invoke(obj);
//暴力訪問私有方法
package pack03_reflect;
import java.lang.reflect.Method;
public class Demo04GetMethod {
public static void main(String[] args)
throws Exception {
// 1:獲取類的Class對(duì)象
Class<?> clazz = Class.forName("pack03_reflect.Student");
Object obj = clazz.newInstance();
//獲取私有方法
Method method = clazz.getDeclaredMethod("eat");
//對(duì)于私有的成員贬蛙,必須設(shè)置暴力訪問
method.setAccessible(true);
method.invoke(obj);
}
}
注意:
例題1:
package pack04_reflect;
import java.lang.reflect.Field;
public class Demo02GetFieldStatic {
public static void main(String[] args) throws Exception{
Class<?> clazz = Class.forName("pack04_reflect.Student");
Field field = clazz.getDeclaredField("classId");
field.setAccessible(true);
//靜態(tài)的變量反射不需要對(duì)象,直接寫null
// field.set(null, "黑馬66期");
field.set(null,? "黑馬66期");
System.out.println(Student.getClassId());
}
}
例題2:反射靜態(tài)方法
package pack04_reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Demo03GetFieldStatic {
public static void main(String[] args) throws Exception{
Class<?> clazz = Class.forName("pack04_reflect.Student");
//反射靜態(tài)方法
Method method = clazz.getMethod("sleep");
//靜態(tài)方法調(diào)用的時(shí)候不需要對(duì)象即可
method.invoke(null);
}
}
案例:把文件中的鍵值,鍵是方法,值是參數(shù),進(jìn)行反射調(diào)用
package pack05_test;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
import java.util.Set;
public class Demo01Test {
public static void main(String[] args) throws Exception {
// 1:從文件中將鍵值對(duì)讀取到Properties集合
// 1.1:創(chuàng)建Properties對(duì)象
Properties prop = new Properties();
// 1.2讀取數(shù)據(jù)
prop.load(new FileReader("info.txt"));
// 2:反射
// 2.1 獲取類的Class對(duì)象
Class<?> clazz = Class.forName("pack05_test.User");
// 2.2 創(chuàng)建對(duì)象
Object obj = clazz.newInstance();
// 3:遍歷集合
Set<String> set = prop.stringPropertyNames();
for (String key : set) { // uid username password
// 將獲取的鍵拼接成方法的名字 setUid setUsername setPassword
String methodName = "set" + key.substring(0, 1).toUpperCase() + key.substring(1);
// 反射以上獲取的方法
Method method = clazz.getMethod(methodName, String.class);
// 獲取Properties的值
String value = prop.getProperty(key);
// 調(diào)用方法
method.invoke(obj, value);
}
System.out.println(obj);
}
}
//把類全名和方法以鍵值對(duì)的方式放在txt文件中,在進(jìn)行讀取調(diào)用方法
package pack05_test;
import java.io.FileReader;
import java.lang.reflect.Method;
import java.util.Properties;
public class Demo02Test {
public static void main(String[] args) throws Exception {
Properties prop = new Properties();
prop.load(new FileReader("config.txt"));
// 從prop集合中獲取信息
// 1:獲取類的全名
String className = prop.getProperty("className");
// 2:獲取類的方法名
String methodName = prop.getProperty("methodName");
// 3:反射
// 3.1 創(chuàng)建類的Class對(duì)象
Class<?> clazz = Class.forName(className);
// 3.2 創(chuàng)建對(duì)象
Object obj = clazz.newInstance();
// 3.3 獲取方法
Method method = clazz.getMethod(methodName);
// 3.4 調(diào)用方法
method.invoke(obj);
}
}
案例:
//通用工具
package pack05_test;
import java.lang.reflect.Field;
public class Demo03Test {
//將obj對(duì)象的name變量賦值為value? ? 對(duì)象? ? ? ? 變量名? ? ? ? ? ? ? ? 值
public static void setVariable(Object obj, String name, Object value) throws NoSuchFieldException, SecurityException,
IllegalArgumentException, IllegalAccessException{
Class<?> clazz = obj.getClass();
Field field = clazz.getDeclaredField(name);
//設(shè)置暴力訪問
field.setAccessible(true);
//將obj對(duì)象的name變量設(shè)置為value
field.set(obj, value);
}
public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException,
IllegalAccessException {
Student stu = new Student();
setVariable(stu, "name", "劉濤");
setVariable(stu, "age", 35);
System.out.println(stu);
System.out.println("-----------------");
User user = new User();
setVariable(user, "uid", "it001");
setVariable(user, "username", "lft");
setVariable(user, "password", "123");
System.out.println(user);
}
}
反射案例:變參方法
package pack06_kuozhan;
import java.lang.reflect.Method;
public class Demo01Test {
public void func1(String[] array){
System.out.println("數(shù)組長(zhǎng)度:"+array.length);
}
public void func2(String... array){
System.out.println("數(shù)組長(zhǎng)度:"+array.length);
}
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("pack06_kuozhan.Demo01Test");
Object obj = clazz.newInstance();
Method method = clazz.getMethod("func2", String[].class);
// method.invoke(obj, new String[]{"hello","world"}); //"hello","world"
// method.invoke(obj, "hello","world");
method.invoke(obj, new Object[]{new String[]{"hello","world"}}); ///new String[]{"hello","world"}
}
裝飾設(shè)計(jì)模式:例題1
package pack06_kuozhan;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
//裝飾模式
abstract class Person{
public abstract void eat();
}
class Student extends Person{
String name;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name) {
super();
this.name = name;
}
@Override
public void eat() {
System.out.println(name + "學(xué)生食堂吃飯");
}
}
class Worker extends Person{
@Override
public void eat() {
System.out.println("工人工地吃飯");
}
}
class BufferedPerson{
Person? p;
public BufferedPerson() {
}
public BufferedPerson(Person p) {
this.p = p;
}
public void superEat(){
System.out.println("來一杯");
p.eat();
System.out.println("抽一根");
}
}
public class Demo02Test {
public static void main(String[] args) throws FileNotFoundException {
BufferedPerson bufp = new BufferedPerson(new Student("劉濤"));
bufp.superEat();
// BufferedReader bufr = new BufferedReader(new FileReader("a.txt")); //read
// readLine();
}
}
}
//案例:在給定泛型的集合中添加,任意類型
package pack05_test;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class Demo04Test {
public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(23);
list.add(35);
list.add(29);
// list.add("hello");
//請(qǐng)用所學(xué)知識(shí)在集合中添加字符
//ArrayList.java ----> ArrayList.class --->Class對(duì)象
//繞過編譯器直接訪問ArrayList的class文件
Class<? > clazz = list.getClass();
//通過反射獲取add方法
Method method = clazz.getMethod("add", Object.class);
//調(diào)用方法
//此刻實(shí)際上是在調(diào)用Arraylist的add方法
method.invoke(list, "hello");
method.invoke(list, true);
method.invoke(list, 12.34);
System.out.println(list);
}
}
注意:在現(xiàn)實(shí)編程中有的方法或者變量會(huì)加密的,不讓你進(jìn)行反射,而讓你反射的則不會(huì)加密.
例題:在方法里面的可變參數(shù),可以傳一個(gè)二維數(shù)組
package comitheaim_02;
import java.lang.reflect.Method;
public class Test6 {
public void func1 (String[] array) {
System.out.println("數(shù)組長(zhǎng)度:" + array.length);
}
public void func2 (String...array) {
System.out.println("數(shù)組長(zhǎng)度:" + array.length);
}
public void func3(String[][]...array) {
System.out.println("數(shù)組長(zhǎng)度:" + array.length);
}
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("comitheaim_02.Test6");
Object obj = clazz.newInstance();
Method m1 = clazz.getMethod("func1", String[].class);
Method m = clazz.getMethod("func2", String[].class);
Method m2 = clazz.getMethod("func3", String[][][].class);
//m2.invoke(obj, new Object[]{new Object[] {new String[]{"在哪","在的","咋你就好","是的"}},});
//它會(huì)把數(shù)組分開分別參數(shù)里面的數(shù)組,但是拆開以后是字符和數(shù)組不匹配,所有數(shù)組里面在放數(shù)組,這樣它拆了換是數(shù)組,這樣就可以賦值了.
m.invoke(obj, new Object[]{new String[]{"hello","world"}});
m1.invoke(obj, new Object[]{new String[]{"hello","world","java"}});
String[] str1 = {"a","b"};
String[] str2 = {"b","c"};
String[][] strs = {str1,str2};
//m2.invoke(obj, strs);
String[] str3 = {"d","j"};
String[] str4 = {"r","g"};
String[][] strss = {str3,str4};
//Object[] ob = {strs,strss};
String[][][] s1 = {strs,strss};
//m2.invoke(obj, new Object[]{strs,strss});
m2.invoke(obj, new Object[]{s1});
//m2.invoke(obj, new Object[]{new String[][]{new String[]{"hello","world"},new String[]{"你好","在嗎"}},});
}
}