一、網絡編程
計算機網絡是指將地理位置不同的具有獨立功能的多臺計算機及其外部設備,通過通信線路連接起來,在網絡操作系統,網絡管理軟件及網絡通信協議的管理和協調下,實現資源共享和信息傳遞的計算機系統。網絡編程就是用來實現網絡互連的不同計算機上運行的程序間可以進行數據交換。
1.IP概述
每個設備在網絡中的唯一標識,每臺網絡終端在網絡中都有一個獨立的地址,我們在網絡中傳輸數據就是使用這個地址。
IPv4:4個字節組成,4個0-255。大概42億,30億都在北美,亞洲4億。2011年初已經用盡。
IPv6:8組,每組4個16進制數。
2.端口號
每個程序在設備上的唯一標識,每個網絡程序都需要綁定一個端口號,傳輸數據的時候除了確定發到哪臺機器上,還要明確發到哪個程序。端口號範圍從0-65535,編寫網絡應用就需要綁定一個端口號,儘量使用1024以上的,1024以下的基本上都被系統程序佔用了。
3.協議
爲計算機網絡中進行數據交換而建立的規則、標準或約定的集合。
UDP 用戶數據報協議,類似寫信,面向無連接,數據不安全,速度快。不區分客戶端與服務端。是一個簡單的面向數據報的運輸層協議。UDP不提供可靠性,它只是把應用程序傳給IP層的數據報發送出去,但是並不能保證它們能到達目的地。由於UDP在傳輸數據報前不用在客戶和服務器之間建立一個連接,且沒有超時重發等機制,故而傳輸速度很快。
TCP 傳輸控制協議,類似打電話,面向連接(三次握手),數據安全,速度略低。分爲客戶端和服務端。
三次握手: 客戶端先向服務端發起請求, 服務端響應請求, 傳輸數據。
提供的是面向連接、可靠的字節流服務。當客戶和服務器彼此交換數據前,必須先在雙方之間建立一個TCP連接,之後才能傳輸數據。TCP提供超時重發,丟棄重複數據,檢驗數據,流量控制等功能,保證數據能從一端傳到另一端。
4.Socket
網絡上具有唯一標識的IP地址和端口號組合在一起才能構成唯一能識別的標識符套接字。
通信的兩端都有Socket,網絡通信其實就是Socket間的通信,數據在兩個Socket間通過IO流傳輸。Socket在應用程序中創建,通過一種綁定機制與驅動程序建立關係,告訴自己所對應的IP和port。
5.UDP
1.發送Send
創建DatagramSocket,隨機端口號
創建DatagramPacket,指定數據,長度,地址,端口
使用DatagramSocket發送DatagramPacket
關閉DatagramSocket
2.接收Receive
創建DatagramSocket,指定端口號
創建DatagramPacket,指定數組,長度
使用DatagramSocket接收DatagramPacket
關閉DatagramSocket
3.接收方獲取ip和端口號
String ip = packet.getAddress().getHostAddress();
int port = packet.getPort();
6.UDP傳輸優化
接收端Receive
DatagramSocket socket = new DatagramSocket(6666); //相當於創建碼頭
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().getHostAddress();
System.out.println(ip + ":" + new String(arr,0,len));
}
發送端Send
DatagramSocket socket = new DatagramSocket();
Scanner sc = new Scanner(System.in);
while(true) {
String str = sc.nextLine();
if("quit".equals(str)) break;
DatagramPacket packet = new DatagramPacket(str.getBytes(), str.getBytes().length, InetAddress.getByName("127.0.0.1"), 6666);
socket.send(packet);
}
socket.close();
7.UDP傳輸多線程
發送和接收在一個窗口完成
public class Demo3MoreThread {
public static void main(String[] args) {
new Receive().start();
new Send().start();
}
}
class Receive extends Thread {
public void run() {
try {
DatagramSocket socket = new DatagramSocket(6666);
DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
while(true) {
socket.receive(packet);
byte[] arr = packet.getData();
int len = packet.getLength();
String ip = packet.getAddress().getHostAddress();
System.out.println(ip + ":" + new String(arr,0,len));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Send extends Thread {
public void run() {
try {
DatagramSocket socket = new DatagramSocket();
Scanner sc = new Scanner(System.in);
while(true) {
String str = sc.nextLine();
if("quit".equals(str))
break;
DatagramPacket packet = new DatagramPacket(str.getBytes(), str.getBytes().length, InetAddress.getByName("127.0.0.1"), 6666);
socket.send(packet);
}
socket.close();
}catch (IOException e) {
e.printStackTrace();
}
}
}
二、TCP協議
1.客戶端
創建Socket連接服務端(指定ip地址,端口號)通過ip地址找對應的服務器
調用Socket的getInputStream()和getOutputStream()方法獲取和服務端相連的IO流
輸入流可以讀取服務端輸出流寫出的數據
輸出流可以寫出數據到服務端的輸入流
2.服務端
創建ServerSocket(需要指定端口號)
調用ServerSocket的accept()方法接收一個客戶端請求,得到一個Socket
調用Socket的getInputStream()和getOutputStream()方法獲取和客戶端相連的IO流
輸入流可以讀取客戶端輸出流寫出的數據
輸出流可以寫出數據到客戶端的輸入流
3.TCP協議代碼優化
客戶端
Socket socket = new Socket("127.0.0.1", 9999);
InputStream is = socket.getInputStream(); //獲取輸入流
OutputStream os = socket.getOutputStream(); //獲取輸出流
BufferedReader br = new BufferedReader(new InputStreamReader(is));
PrintStream ps = new PrintStream(os);
System.out.println(br.readLine());
ps.println("我想報名就業班");
System.out.println(br.readLine());
ps.println("爺不學了");
socket.close();
服務端
ServerSocket server = new ServerSocket(9999); //創建服務器
Socket socket = server.accept(); //接受客戶端的請求
InputStream is = socket.getInputStream(); //獲取輸入流
OutputStream os = socket.getOutputStream(); //獲取輸出流
BufferedReader br = new BufferedReader(new InputStreamReader(is));
PrintStream ps = new PrintStream(os);
ps.println("歡迎諮詢傳智播客");
System.out.println(br.readLine());
ps.println("報滿了,請報下一期吧");
System.out.println(br.readLine());
server.close();
socket.close();
4.服務端是多線程
ServerSocket server = new ServerSocket(9999); //創建服務器
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());
ps.println("歡迎諮詢傳智播客");
System.out.println(br.readLine());
ps.println("報滿了,請報下一期吧");
System.out.println(br.readLine());
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
}