黑馬程式設計師--網路程式設計知識點總結
網路程式設計三要素
IP,埠,協議。
1.IP:在Internet上,每一臺通訊實體(這個通訊實體可以是路由器的某一埠,計算機和伺服器等裝置)都有唯一表示的IP地址,之前都是IPv4的但在2011年已經用盡,現在正向ipv6時代邁進
2.埠:在裝置上的唯一標識,範圍在0–65535之間,編寫網路應用就需要繫結一個埠號,儘量使用1024以上的,1024以下的基本上都被系統程式佔用了。
3.協議:為計算機網路中進行資料交換而建立的規則、標準或約定的集合。
UDP
面向無連線,資料不安全,速度快。不區分客戶端與服務端。
TCP
面向連線(三次握手),資料安全,速度略低。分為客戶端和服務端。
三次握手: 客戶端先向服務端發起請求, 服務端響應請求, 傳輸資料
Socket套接字
網路上具有唯一標識的IP地址和埠號組合在一起才能構成唯一能識別的識別符號套接字。
通訊的兩端都有Socket。
網路通訊其實就是Socket間的通訊。
資料在兩個Socket間通過IO流傳輸。
Socket在應用程式中建立,通過一種繫結機制與驅動程式建立關係,告訴自己所對應的IP和port
UDP的傳輸
傳送Send
建立DatagramSocket, 隨機埠號
建立DatagramPacket, 指定資料, 長度, 地址, 埠
使用DatagramSocket傳送DatagramPacket
關閉DatagramSocket
public static void main(String[] args) throws IOException {
String s = "為夢想奮鬥";//要傳送的資料
DatagramSocket ds = new DatagramSocket();//建立Socket物件 相當於建立碼頭
DatagramPacket dsp = //建立Packet 相當於建立集裝箱
new DatagramPacket(s.getBytes(), s.getBytes().length,InetAddress.getByName("127.0.0.1" ),12345);
ds.send(dsp); //傳送資料
ds.close();
}
接收Receive
建立DatagramSocket, 指定埠號
建立DatagramPacket, 指定陣列, 長度
使用DatagramSocket接收DatagramPacket
關閉DatagramSocket
從DatagramPacket中獲取資料
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket(12345); //建立Socket相當於建立一個碼頭
DatagramPacket packet = new DatagramPacket(new byte[1024],1024);//建立Packet相當於建立一個集裝箱
socket.receive(packet);
byte[] arr = packet.getData(); //從集裝箱中獲取資料
int len = packet.getLength(); //獲取發過來的有效位元組個數
System.out.println(new String(arr,0,len));
socket.close();
}
UDP傳輸的優化
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket();//建立Socket物件 相當於建立碼頭
Scanner sc = new Scanner(System.in);//鍵盤錄入
while(true){
String line = sc.nextLine();//接收鍵盤錄入內容
if("over".equals(line)){ //相當於圖形化介面的差號
break;
}
DatagramPacket dsp = //建立Packet 相當於建立集裝箱
new DatagramPacket(line.getBytes(), line.getBytes().length,InetAddress.getByName("127.0.0.1"),12345);
ds.send(dsp); //傳送資料
}
ds.close();
}
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket(12345); //建立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().getCanonicalHostName();//獲取IP地址
int port = packet.getPort(); //獲取埠號
System.out.println(ip + ":" + port + ":" + new String(arr,0,len));
}
}
}
TCP傳輸
客戶端
普通方式和優化方式
public static void main(String[] args) throws UnknownHostException, IOException {
//demo();
Socket socket = new Socket("127.0.0.1",9999);//建立Socket,並指定IP和埠號
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));//對輸入流包裝
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("相信自己一定可以");//向伺服器寫出資料
System.out.println(br.readLine());//讀取伺服器的內容並列印
socket.close();
}
private static void demo() throws UnknownHostException, IOException {
Socket socket = new Socket("127.0.0.1",9999);//建立Socket,並指定IP和埠號
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());
}
}
服務端
普通方式
private static void demo() throws IOException {
ServerSocket server = new ServerSocket(9999);//建立ServerSocket t物件並連線埠
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));//將陣列轉化為字串
server.close();
socket.close();
}
優化方式
private static void demo1() throws IOException {
ServerSocket server = new ServerSocket(9999);//建立ServerSocket t物件並連線埠
Socket socket = server.accept(); //接收客戶端的請求
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));//對輸入流包裝
PrintStream ps = new PrintStream(socket.getOutputStream());
System.out.println(br.readLine());//讀取伺服器的內容並列印
ps.println("加油加油加油"); //向伺服器寫出資料
socket.close();//關閉套接字,順便關閉流
}
多執行緒方式
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(9999);//建立ServerSocket t物件並連線埠
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());
System.out.println(br.readLine());//讀取伺服器的內容並列印
ps.println("努力努力努力"); //向伺服器寫出資料
socket.close();//關閉套接字,順便關閉流
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
練習:客戶端向伺服器寫字串,伺服器將字串反轉後寫回,客戶端再次讀取到是反轉後的字串
客戶端:
public static void main(String[] args) throws UnknownHostException, IOException {
Socket socket = new Socket("127.0.0.1", 23445);//建立客戶端物件並指定IP和埠
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream ps = new PrintStream(socket.getOutputStream());
Scanner sc = new Scanner(System.in);
ps.println(sc.nextLine()); //將鍵盤錄入的字串放在伺服器中
System.out.println(br.readLine());//列印反轉後的字串
socket.close();
}
服務端:
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(23445);//建立服務端伺服器,並連線埠
System.out.println("伺服器啟動");
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());
String line = br.readLine();//獲取字串
line = new StringBuilder(line).reverse().toString();//將字串放在Stringbuilder中反轉並轉回字串
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}