26 API-網路程式設計(網路概述,Socket通訊機制,UDP協議傳送和接收資料,TCP協議傳送和接收資料)
1:網路程式設計(理解)
(1)網路程式設計:用Java語言實現計算機間資料的資訊傳遞和資源共享(2)網路程式設計模型
l網路模型一般是指 OSI(Open System Interconnection開放系統互連)參考模型 TCP/IP參考模型(3)網路程式設計的三要素
A:IP地址
a:點分十進位制
計算機只能識別二進位制的資料,所以我們的IP地址應該是一個二進位制的資料。
但是呢,我們配置的IP地址確不是二進位制的,為什麼呢?
IP:192.168.1.100
換算:11000000 10101000 00000001 01100100
假如真是:11000000 10101000 00000001 01100100的話。
我們如果每次再上課的時候要配置該IP地址,記憶起來就比較的麻煩。
所以,為了方便表示IP地址,我們就把IP地址的每一個位元組上的資料換算成十進位制,然後用.分開來表示:
既"點分十進位制"
b:IP地址的組成
網路號段+主機號段
A類:第一號段為網路號段+後三段的主機號段
一個網路號:256*256*256 = 16777216
B類:前二號段為網路號段+後二段的主機號段
一個網路號:256*256 = 65536
C類:前三號段為網路號段+後一段的主機號段
一個網路號:256
c:IP地址的分類
A類1.0.0.1---127.255.255.254
(1)10.X.X.X是私有地址(私有地址就是在網際網路上不使用,而被用在區域網絡中的地址)
(2)127.X.X.X是保留地址,用做迴圈測試用的。
B類128.0.0.1---191.255.255.254172.16.0.0---172.31.255.255是私有地址。169.254.X.X是保留地址。
C類192.0.0.1---223.255.255.254192.168.X.X是私有地址
D類224.0.0.1---239.255.255.254
E類240.0.0.1---247.255.255.254
特殊的IP地址:
127.0.0.1 迴環地址(表示本機)
x.x.x.255 廣播地址
x.x.x.0 網路地址
d:dos命令
ipconfig 檢視本機ip地址
ping 後面跟ip地址。測試本機與指定的ip地址間的通訊是否有問題
e:InetAddress
* 看InetAddress的成員方法:
* public static InetAddress getByName(String host):根據主機名或者IP地址的字串表示得到IP地址物件(此方法為單例設計模式)
*/
public class InetAddressDemo { public static void main(String[] args) throws UnknownHostException { // public static InetAddress getByName(String host) // InetAddress address = InetAddress.getByName("liuyi"); // InetAddress address = InetAddress.getByName("192.168.12.92"); InetAddress address = InetAddress.getByName("192.168.12.63"); // 獲取兩個東西:主機名,IP地址 // public String getHostName() String name = address.getHostName(); // public String getHostAddress() String ip = address.getHostAddress(); System.out.println(name + "---" + ip); } }
B:埠
是應用程式的標識。範圍:0-65535。其中0-1024不建議使用為系統保留埠。
C:協議: 通訊的規則
UDP:資料打包,有限制,不連線,效率高,不可靠TCP:建立資料通道,無限制,效率低,可靠
(3)Socket機制
A:通訊兩端都應該有Socket物件B:所有的通訊都是通過Socket間的IO進行操作的
(4)UDP協議傳送和接收資料(掌握 )
建立UDP傳送端的Socket物件
建立資料並把資料打包
傳送資料
釋放資源
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/*
* UDP協議傳送資料:
* A:建立傳送端Socket物件
* B:建立資料,並把資料打包
* C:呼叫Socket物件的傳送方法傳送資料包
* D:釋放資源
*/
public class SendDemo {
public static void main(String[] args) throws IOException {
// 建立傳送端Socket物件
// DatagramSocket()
DatagramSocket ds = new DatagramSocket();
// 建立資料,並把資料打包
// DatagramPacket(byte[] buf, int length, InetAddress address, int port)
// 建立資料
byte[] bys = "hello,udp,我來了".getBytes();
// 長度
int length = bys.length;
// IP地址物件
InetAddress address = InetAddress.getByName("192.168.12.92");
// 埠
int port = 10086;
DatagramPacket dp = new DatagramPacket(bys, length, address, port);
// 呼叫Socket物件的傳送方法傳送資料包
// public void send(DatagramPacket p)
ds.send(dp);
// 釋放資源
ds.close();
}
}
接收:
建立UDP接收端的Socket物件
建立資料包用於接收資料
接收資料
解析資料包
釋放資源
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/*
* UDP協議接收資料:
* A:建立接收端Socket物件
* B:建立一個數據包(接收容器)
* C:呼叫Socket物件的接收方法接收資料
* D:解析資料包,並顯示在控制檯
* E:釋放資源
*/
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
// 建立接收端Socket物件
// DatagramSocket(int port)
DatagramSocket ds = new DatagramSocket(10086);
// 建立一個數據包(接收容器)
// DatagramPacket(byte[] buf, int length)
byte[] bys = new byte[1024];
int length = bys.length;
DatagramPacket dp = new DatagramPacket(bys, length);
// 呼叫Socket物件的接收方法接收資料
// public void receive(DatagramPacket p)
ds.receive(dp); // 阻塞式
// 解析資料包,並顯示在控制檯
// 獲取對方的ip
// public InetAddress getAddress()
InetAddress address = dp.getAddress();
String ip = address.getHostAddress();
// public byte[] getData():獲取資料緩衝區
// public int getLength():獲取資料的實際長度
byte[] bys2 = dp.getData();
int len = dp.getLength();
String s = new String(bys2, 0, len);
System.out.println(ip + "傳遞的資料是:" + s);
// 釋放資源
ds.close();
}
}
(5)TCP協議傳送和接收資料(掌握 )
建立TCP客戶端的Socket物件
獲取輸出流,寫資料
釋放資源
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
/*
* TCP協議傳送資料:
* A:建立傳送端的Socket物件
* 這一步如果成功,就說明連線已經建立成功了。
* B:獲取輸出流,寫資料
* C:釋放資源
*
* 連線被拒絕。TCP協議一定要先看伺服器。
* java.net.ConnectException: Connection refused: connect
*/
public class ClientDemo {
public static void main(String[] args) throws IOException {
// 建立傳送端的Socket物件
// Socket(InetAddress address, int port)
// Socket(String host, int port)
// Socket s = new Socket(InetAddress.getByName("192.168.12.92"), 8888);
Socket s = new Socket("192.168.12.92", 8888);
// 獲取輸出流,寫資料
// public OutputStream getOutputStream()
OutputStream os = s.getOutputStream();
os.write("hello,tcp,我來了".getBytes());
// 釋放資源
s.close();
}
}
接收:
建立TCP伺服器端的Socket物件
監聽客戶端連線
獲取輸入流,讀取資料
釋放資源
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
/*
* TCP協議接收資料:
* A:建立接收端的Socket物件
* B:監聽客戶端連線。返回一個對應的Socket物件
* C:獲取輸入流,讀取資料顯示在控制檯
* D:釋放資源
*/
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 建立接收端的Socket物件
// ServerSocket(int port)
ServerSocket ss = new ServerSocket(8888);
// 監聽客戶端連線。返回一個對應的Socket物件
// public Socket accept()
Socket s = ss.accept(); // 偵聽並接受到此套接字的連線。此方法在連線傳入之前一直阻塞。
// 獲取輸入流,讀取資料顯示在控制檯
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys); // 阻塞式方法
String str = new String(bys, 0, len);
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip + "---" + str);
// 釋放資源
s.close();
// ss.close(); //這個不應該關閉
}
}
(6)案例:
A:UDP
a:最基本的UDP協議傳送和接收資料
b:把傳送資料改進為鍵盤錄入
c:一個簡易聊天小程式並用多執行緒改進
B:TCP
a:最基本的TCP協議傳送和接收資料
b:伺服器給出反饋
c:客戶端鍵盤錄入伺服器控制檯輸出
d:客戶端鍵盤錄入伺服器寫到文字檔案
e:客戶端讀取文字檔案伺服器控制檯輸出
f:客戶端讀取文字檔案伺服器寫到文字檔案
client
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
/*
* 按照我們正常的思路加入反饋資訊,結果卻沒反應。為什麼呢?
* 讀取文字檔案是可以以null作為結束資訊的,但是呢,通道內是不能這樣結束資訊的。
* 所以,伺服器根本就不知道你結束了。而你還想伺服器給你反饋。所以,就相互等待了。
*
* 如何解決呢?
* A:在多寫一條資料,告訴伺服器,讀取到這條資料說明我就結束,你也結束吧。
* 這樣做可以解決問題,但是不好。
* B:Socket物件提供了一種解決方案
* public void shutdownOutput()
*/
public class UploadClient {
public static void main(String[] args) throws IOException {
// 建立客戶端Socket物件
Socket s = new Socket("192.168.12.92", 11111);
// 封裝文字檔案
BufferedReader br = new BufferedReader(new FileReader(
"InetAddressDemo.java"));
// 封裝通道內流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
String line = null;
while ((line = br.readLine()) != null) { // 阻塞
bw.write(line);
bw.newLine();
bw.flush();
}
//自定義一個結束標記
// bw.write("over");
// bw.newLine();
// bw.flush();
//Socket提供了一個終止,它會通知伺服器你別等了,我沒有資料過來了
s.shutdownOutput();
// 接收反饋
BufferedReader brClient = new BufferedReader(new InputStreamReader(
s.getInputStream()));
String client = brClient.readLine(); // 阻塞
System.out.println(client);
// 釋放資源
br.close();
s.close();
}
}
Sever
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class UploadServer {
public static void main(String[] args) throws IOException {
// 建立伺服器端的Socket物件
ServerSocket ss = new ServerSocket(11111);
// 監聽客戶端連線
Socket s = ss.accept();// 阻塞
// 封裝通道內的流
BufferedReader br = new BufferedReader(new InputStreamReader(
s.getInputStream()));
// 封裝文字檔案
BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java"));
String line = null;
while ((line = br.readLine()) != null) { // 阻塞
// if("over".equals(line)){
// break;
// }
bw.write(line);
bw.newLine();
bw.flush();
}
// 給出反饋
BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
bwServer.write("檔案上傳成功");
bwServer.newLine();
bwServer.flush();
// 釋放資源
bw.close();
s.close();
}
}
g:上傳圖片
Client
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
public class UploadClient {
public static void main(String[] args) throws IOException {
// 建立客戶端Socket物件
Socket s = new Socket("192.168.12.92", 19191);
// 封裝圖片檔案
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
"林青霞.jpg"));
// 封裝通道內的流
BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
bos.flush();
}
s.shutdownOutput();
// 讀取反饋
InputStream is = s.getInputStream();
byte[] bys2 = new byte[1024];
int len2 = is.read(bys2);
String client = new String(bys2, 0, len2);
System.out.println(client);
// 釋放資源
bis.close();
s.close();
}
}
Server
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class UploadServer {
public static void main(String[] args) throws IOException {
// 建立伺服器Socket物件
ServerSocket ss = new ServerSocket(19191);
// 監聽客戶端連線
Socket s = ss.accept();
// 封裝通道內流
BufferedInputStream bis = new BufferedInputStream(s.getInputStream());
// 封裝圖片檔案
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("mn.jpg"));
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
bos.flush();
}
// 給一個反饋
OutputStream os = s.getOutputStream();
os.write("圖片上傳成功".getBytes());
bos.close();
s.close();
}
}
h:多執行緒改進上傳檔案
Server
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class UploadServer {
public static void main(String[] args) throws IOException {
// 建立伺服器Socket物件
ServerSocket ss = new ServerSocket(11111);
while (true) {
Socket s = ss.accept();
new Thread(new UserThread(s)).start();
}
}
}
Thread
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class UploadClient {
public static void main(String[] args) throws IOException {
// 建立客戶端Socket物件
Socket s = new Socket("192.168.12.92", 11111);
// 封裝文字檔案
// BufferedReader br = new BufferedReader(new FileReader(
// "InetAddressDemo.java"));
BufferedReader br = new BufferedReader(new FileReader(
"ReceiveDemo.java"));
// 封裝通道內流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
String line = null;
while ((line = br.readLine()) != null) { // 阻塞
bw.write(line);
bw.newLine();
bw.flush();
}
// Socket提供了一個終止,它會通知伺服器你別等了,我沒有資料過來了
s.shutdownOutput();
// 接收反饋
BufferedReader brClient = new BufferedReader(new InputStreamReader(
s.getInputStream()));
String client = brClient.readLine(); // 阻塞
System.out.println(client);
// 釋放資源
br.close();
s.close();
}
}