26.02_網(wǎng)絡(luò)編程三要素之IP概述(掌握)
- 每個(gè)設(shè)備在網(wǎng)絡(luò)中的唯一標(biāo)識(shí)
- 每臺(tái)網(wǎng)絡(luò)終端在網(wǎng)絡(luò)中都有一個(gè)獨(dú)立的地址,我們?cè)诰W(wǎng)絡(luò)中傳輸數(shù)據(jù)就是使用這個(gè)地址献丑。
-
ipconfig
:查看本機(jī)IP192.168.12.42 -
ping
:測試連接192.168.40.62 - 本地回路地址:127.0.0.1 , 255.255.255.255是廣播地址
- IPv4:4個(gè)字節(jié)組成,4個(gè)0-255侠姑。大概42億创橄,30億都在北美,亞洲4億莽红。2011年初已經(jīng)用盡妥畏。
- IPv6:8組邦邦,每組4個(gè)16進(jìn)制數(shù)。
1a2b:0000:aaaa:0000:0000:0000:aabb:1f2f
-
1a2b::aaaa:0000:0000:0000:aabb:1f2f
//兩個(gè)::代表省略了中間的0 1a2b:0000:aaaa::aabb:1f2f
26.03_網(wǎng)絡(luò)編程三要素之端口號(hào)概述(掌握)
- 每個(gè)程序在設(shè)備上的唯一標(biāo)識(shí)
- 每個(gè)網(wǎng)絡(luò)程序都需要綁定一個(gè)端口號(hào)醉蚁,傳輸數(shù)據(jù)的時(shí)候除了確定發(fā)到哪臺(tái)機(jī)器上燃辖,還要明確發(fā)到哪個(gè)程序。
- 端口號(hào)范圍從
0-65535
- 編寫網(wǎng)絡(luò)應(yīng)用就需要綁定一個(gè)端口號(hào)网棍,盡量使用1024以上的郭赐,1024以下的基本上都被系統(tǒng)程序占用了。
mysql: 3306
oracle: 1521
web: 80
tomcat: 8080
QQ: 4000
feiQ: 2425
26.04_網(wǎng)絡(luò)編程三要素協(xié)議(掌握)
- 為計(jì)算機(jī)網(wǎng)絡(luò)中進(jìn)行數(shù)據(jù)交換而建立的規(guī)則确沸、標(biāo)準(zhǔn)或約定的集合捌锭。
-
UDP (類似發(fā)短信,對(duì)方可以不開機(jī)罗捎,甚至是假號(hào)碼)
- 面向無連接观谦,數(shù)據(jù)不安全,速度快桨菜。不區(qū)分客戶端與服務(wù)端豁状。
-
TCP (類似打電話,撥通才能打通話倒得,http的底層就是TCP)
* 面向連接(三次握手)泻红,數(shù)據(jù)安全,速度略低霞掺。分為客戶端和服務(wù)端谊路。- 三次握手: 1客戶端先向服務(wù)端發(fā)起請(qǐng)求, 2服務(wù)端響應(yīng)請(qǐng)求, 3傳輸數(shù)據(jù)
26.05_Socket通信原理圖解(了解)
- 網(wǎng)絡(luò)上具有唯一標(biāo)識(shí)的IP地址和端口號(hào)組合在一起才能構(gòu)成唯一能識(shí)別的標(biāo)識(shí)符套接字。
- 通信的兩端都有
Socket
菩彬。 - 網(wǎng)絡(luò)通信其實(shí)就是
Socket
間的通信缠劝。 - 數(shù)據(jù)在兩個(gè)
Socket
間通過IO流傳輸。 -
Socket
在應(yīng)用程序中創(chuàng)建骗灶,通過一種綁定機(jī)制與驅(qū)動(dòng)程序建立關(guān)系惨恭,告訴自己所對(duì)應(yīng)的IP和port。
26.06_網(wǎng)絡(luò)編程(UDP傳輸)(了解)
- 1.發(fā)送Send
byte[] d = "你好啊!".getBytes();
InetAddress ip = InetAddress.getByName("127.0.0.1");
DatagramSocket socket = new DatagramSocket(); //創(chuàng)建socket耙旦,相當(dāng)于是碼頭脱羡,隨機(jī)端口號(hào)
// 四個(gè)參數(shù)是: 數(shù)據(jù)、數(shù)據(jù)長度免都、地址锉罐、端口號(hào)
DatagramPacket data = new DatagramPacket(d, d.length, ip, 3001);
socket.send(data);
- 2.接收Receive
DatagramSocket socket = new DatagramSocket(3001); //指定端口號(hào),創(chuàng)建socket,相當(dāng)于創(chuàng)建碼頭
DatagramPacket data = new DatagramPacket(new byte[1024], 1024); //相當(dāng)于創(chuàng)建集裝箱
socket.receive(data);
socket.close();
byte[] arr = data.getData(); //獲取數(shù)據(jù)
int len = data.getLength(); //獲取有效的字節(jié)個(gè)數(shù)
System.out.println(new String(arr, 0,len));
- 3.接收方獲取ip和端口號(hào)
String ip = packet.getAddress().getHostAddress();
int port = packet.getPort();
26.07_網(wǎng)絡(luò)編程(UDP傳輸優(yōu)化)
- 接收端Receive
DatagramSocket socket = new DatagramSocket(3001); //指定端口號(hào),創(chuàng)建socket琴昆,相當(dāng)于創(chuàng)建碼頭
DatagramPacket data = new DatagramPacket(new byte[1024], 1024); //相當(dāng)于創(chuàng)建集裝箱
while(true) {
socket.receive(data);
byte[] arr = data.getData(); //獲取數(shù)據(jù)
int len = data.getLength(); //獲取有效的字節(jié)個(gè)數(shù)
System.out.println("收到內(nèi)容: " + new String(arr, 0,len));
System.out.println("對(duì)方地址: " + data.getAddress().getHostAddress());
System.out.println("端口: " + data.getPort() + "\r\n");
}
- 發(fā)送端Send
Scanner sc = new Scanner(System.in);
System.out.println("請(qǐng)輸入發(fā)送的內(nèi)容:");
DatagramSocket socket = new DatagramSocket(); //創(chuàng)建socket氓鄙,相當(dāng)于是碼頭
InetAddress ip = InetAddress.getByName("127.0.0.1");
while(true) {
String line = sc.nextLine();
if ("q".equals(line)) break;
byte[] d = line.getBytes(); //數(shù)據(jù)
// 四個(gè)參數(shù)是: 數(shù)據(jù)、數(shù)據(jù)長度业舍、地址抖拦、端口號(hào)
DatagramPacket data = new DatagramPacket(d, d.length, ip, 3001);
socket.send(data); //發(fā)貨
}
socket.close(); //底層是IO流升酣,所以應(yīng)該也關(guān)掉
sc.close();
也可以開啟兩個(gè)線程,一個(gè)線程發(fā)送信息态罪,一個(gè)線程接收消息噩茄。
26.xx_GUI小程序遇到的懵逼知識(shí)點(diǎn)
這中間有一個(gè)GUI的聊天小程序,但是代碼很多复颈,就不粘貼了绩聘,畢竟Java桌面編程不是重點(diǎn),目標(biāo)是JavaEE耗啦,這里就將里面遇到的疑問點(diǎn)整理一下凿菩。
1.快捷鍵 Alt + Shift + L 把選中的變成局部變量
Alt + Shift + z 選中代碼,按此快捷鍵 快速try
Ctrl+Shift+Numpad_Divede(小鍵盤的/號(hào)) 折疊全部方法
Ctrl+Shift+Numpad_Multiply(小鍵盤的*號(hào)) 展開全部方法
2.匿名內(nèi)部類里可以直接調(diào)用外部類的方法帜讲。
// 如下例子衅谷,寫全的方式為: ClassName.this.method(); ClassName為外部類的名字
new Runnable() {
public void run(){
method();
}
};
2.1 如果外部變量是外部類的本地變量(如在方法中定義的變量),
必須聲明成final才能在內(nèi)部類中使用似将,正常是不可以修改這個(gè)變量的获黔,
但如果變量搜索是對(duì)象,可以修改對(duì)象內(nèi)的屬性
2.2 如果外部變量是外部類的成員變量或類變量在验,內(nèi)部類可以直接修改
3. 最常見的基本類型數(shù)組寫法: int[] a = {1,2,3}; byte[] b = {1,2,3};
這種寫法的全寫法是: int[] a = new int[]{1,2,3}; byte[] b = new byte[]{1,2,3}
所以見到 String str = new String(new byte[]{1,2,3}); 不應(yīng)該懵逼玷氏,這僅僅是標(biāo)準(zhǔn)寫法
26.15_生成jar文件
Eclipse
下,生成jar文件
順序是:
1.項(xiàng)目或類上右鍵 --> Export --> Java下的JAR file
2.選擇好要導(dǎo)出jar的類和導(dǎo)出位置腋舌,點(diǎn)擊Next>
3.再次點(diǎn)擊Next>
4.選擇Main Class之后盏触,點(diǎn)擊Finish
26.16_網(wǎng)絡(luò)編程(TCP協(xié)議)(掌握)
- 1.客戶端
- 創(chuàng)建
Socket
連接服務(wù)端(指定ip地址,端口號(hào))通過ip地址找對(duì)應(yīng)的服務(wù)器 - 調(diào)用
Socket
的getInputStream()
和getOutputStream()
方法獲取和服務(wù)端相連的IO流 - 輸入流可以讀取服務(wù)端輸出流寫出的數(shù)據(jù)
- 輸出流可以寫出數(shù)據(jù)到服務(wù)端的輸入流
- 創(chuàng)建
- 2.服務(wù)端
- 創(chuàng)建
ServerSocket
(需要指定端口號(hào)) - 調(diào)用
ServerSocket的accept()
方法接收一個(gè)客戶端請(qǐng)求,得到一個(gè)Socket
- 調(diào)用
Socket
的getInputStream()
和getOutputStream()
方法獲取和客戶端相連的IO流 - 輸入流可以讀取客戶端輸出流寫出的數(shù)據(jù)
- 輸出流可以寫出數(shù)據(jù)到客戶端的輸入流
- 創(chuàng)建
26.17_網(wǎng)絡(luò)編程(TCP協(xié)議代碼優(yōu)化)
- 客戶端
Socket socket = new Socket("127.0.0.1", 3001); //指定ip和端口號(hào)
// 將InputStream 包裝成 BufferedReader 便于直接讀取一行數(shù)據(jù)
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 將OutputStream 包裝成 PrintStream 好處是能直接寫出換行和字符串
PrintStream ps = new PrintStream(socket.getOutputStream());
System.out.println(br.readLine()); //讀取服務(wù)器的回話
ps.println("我是客戶端侦厚,我就是想打個(gè)招呼而已耻陕。。"); //向服務(wù)器回話
socket.close();
- 服務(wù)端
ServerSocket sever = new ServerSocket(3001); //指定端口號(hào)
Socket socket = sever.accept(); //接收客戶端的請(qǐng)求
// 將InputStream 包裝成 BufferedReader 便于直接讀取一行數(shù)據(jù)
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 將OutputStream 包裝成 PrintStream 好處是能直接寫出換行和字符串
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("你好刨沦,我是服務(wù)器,有什么事膘怕?");
System.out.println(br.readLine()); //讀取客戶端的回復(fù)
26.18_網(wǎng)絡(luò)編程(服務(wù)端是多線程的)(掌握)
ServerSocket sever = new ServerSocket(3001); //指定端口號(hào)
while(true) {
final Socket socket = sever.accept(); //接收客戶端的請(qǐng)求
new Thread(){
public void run() {
try {
// 將InputStream 包裝成 BufferedReader 便于直接讀取一行數(shù)據(jù)
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 將OutputStream 包裝成 PrintStream 好處是能直接寫出換行和字符串
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("你好想诅,我是服務(wù)器,有什么事岛心?");
System.out.println(br.readLine()); //讀取客戶端的回復(fù)
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
26.19_網(wǎng)絡(luò)編程(練習(xí))
- 客戶端向服務(wù)器寫字符串(鍵盤錄入),服務(wù)器(多線程)將字符串反轉(zhuǎn)后寫回,客戶端再次讀取到是反轉(zhuǎn)后的字符串
//反轉(zhuǎn)字符串
private String reverString(String str) {
return new StringBuffer(str).reverse().toString();
}
26.20_網(wǎng)絡(luò)編程(客戶端向服務(wù)器上傳文件練習(xí))
- 客戶端部分代碼
Socket socket = new Socket("192.168.3.109",3002);
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println(file.getName()); // 發(fā)送文件名到服務(wù)端
String result = br.readLine(); //讀取服務(wù)器返回結(jié)果
if ("存在".equals(result)) {
System.out.println("您上傳的文件已經(jīng)存在来破,請(qǐng)不要重復(fù)上傳..");
socket.close();
return;
}
System.out.println("文件不存在,開始上傳...");
FileInputStream fis = new FileInputStream(file); //開始讀取文件到服務(wù)器
byte[] data = new byte[10 * 1024];
int len ;
while( (len = fis.read(data)) != -1) {
ps.write(data, 0, len);
}
fis.close();
socket.close();
- 服務(wù)端部分代碼
ServerSocket server = new ServerSocket(3002);
System.out.println("服務(wù)器啟動(dòng)忘古,端口號(hào) 3002 ");
while(true) {
final Socket socket = server.accept();
System.out.println("收到" + socket.getInetAddress().getHostAddress()+ "的請(qǐng)求送朱,開始處理...");
new Thread(){
public void run() {
try {
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
PrintStream ps = new PrintStream(socket.getOutputStream());
String fileName = br.readLine();
File dir = new File("/Users/houwan/Java");
if (!dir.exists()) dir.mkdir(); //不存在就創(chuàng)建文件夾
File file = new File(dir, fileName); //封裝成File對(duì)象
if (file.exists()) {
ps.println("存在");
socket.close(); //關(guān)閉此次服務(wù)
return;
}else ps.println("不存在");
System.out.println("客戶端開始上傳文件...");
FileOutputStream fos = new FileOutputStream(file); //讀取客戶端上傳的文件娘荡,保持到本地
byte[] data = new byte[10 * 1024];
int len ;
while ( (len = is.read(data)) != -1) {
fos.write(data, 0, len);
}
fos.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
};
}.start();
}
END驶沼。
我是小侯爺大年。
在魔都艱苦奮斗,白天是上班族,晚上是知識(shí)服務(wù)工作者失都。
如果讀完覺得有收獲的話,記得關(guān)注和點(diǎn)贊哦庞溜。
非要打賞的話延刘,我也是不會(huì)拒絕的驾荣。