Java進階學習之網路程式設計(4)
阿新 • • 發佈:2022-12-01
目錄
《計算機網路》作為計算機專業的必修課,估計大家對他仍有後怕,這本書很厚,知識面很廣,建議有時間的朋友通篇閱讀和理解。
《計算機網路》作為計算機專業的必修課,估計大家對他仍有後怕,這本書很厚,知識面很廣,建議有時間的朋友通篇閱讀和理解。
1.網路程式設計概述
1.1.目的
通過通訊線路將多臺計算機連線起來,並進行資料傳輸。
1.2.常用的網路協議
1.2.1.TCP
TCP(Transmission Control Protocol):傳輸控制協議,是一種面向連線、可靠的、基於位元組流的傳輸層通訊協議。
TCP的三次握手:
SYN:同步序列編號Synchronize Sequence Numbers
ACK:確認字元Acknowledge character
- 第一次握手:A的TCP客戶端首先建立傳輸控制塊TCB,然後向B傳送連線請求報文段(SYN=1,seq=x),A進入SYN-SENT狀態;
- 第二次握手:B收到連線請求報文後,如同意建立連線,則向A傳送確認(SYN=1,ACK=1,確認號ack=x+1,seq=y),B進入SYN-RCVD狀態;
- 第三次握手:A收到B的確認後,向B發出確認報文(ACK=1,確認號ack=y+1,seq=x+1),A進入ESTABLISHED,B收到A的確認後也進入ESTABLISHED。
TCP四次揮手:
MSL:報文最大存活時間
- A向B傳送連線釋放報文段(FIN=1,seq=u),並停止再發送資料,主動關閉TCP連線,進入FIN-WAIT-1狀態,等待B的確認;
- B收到後發出確認報文段(ACK=1,ack=u+1,seq=v),B進入CLOSE-WAIT狀態,此時TCP連線處於半關閉狀態,A到B的連線釋放;
- A收到B的確認後,進入FIN-WAIT-2狀態,等待B發出連線釋放報文;
- B沒有向A發出資料,B發出連線釋放報文(FIN=1,ACK=1,seq=w,ack=u+1),B進入TIME-WAIT狀態,等待A確認;
- A收到B的連線釋放報文後,發出確認報文(ACK=1,seq=u+1,ack=w+1),A進入TIME-WAIT狀態,此時TCP未釋放掉,經過時間等待計數器設定的時間2MSL後,A進入CLOSED狀態。
1.2.2.UDP
UDP(User Datagram Protocol):使用者資料報協議,是一種無連線的傳輸協議。
特點:
- 不可靠的協議,不建立連線,不進行資料檢查,不等待應答,導致可能會出現資料丟失等現象
- 報頭很短,開銷很小
- 有較好的實用性,傳輸效率很高,受軟體效能、頻寬、收發端主機效能限制
2.Socket網路程式設計
2.1.Socket是什麼
套接字Socket就是雙向通訊中一端的抽象。
Socket由IP地址和埠port確認。
2.2.Socket工作流程
- 伺服器開啟監聽
- 客戶端請求連線
- 確認連線
2.3.案例
服務端編寫:
public class MyServer extends Thread {
private ServerSocket serverSocket;
public MyServer(int port) throws IOException {
serverSocket = new ServerSocket(8888);
System.out.println("服務端已啟動,監聽埠:" + serverSocket.getLocalPort());
}
@Override
public void run() {
Socket server = null;
OutputStream os = null;
DataOutputStream dos = null;
while (true) {
try {
server = serverSocket.accept();
System.out.println(server.getRemoteSocketAddress() + "連線成功!");
os = server.getOutputStream();
dos = new DataOutputStream(os);
dos.writeUTF("hello!");
dos.flush();
dos.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
try {
Thread t = new MyServer(8888);
t.run();
} catch (IOException e) {
e.printStackTrace();
}
}
}
客戶端編寫:
public class MyClient {
public static void main(String[] args) {
Socket client = null;
InputStream is = null;
DataInputStream dis = null;
try {
client = new Socket("127.0.0.1", 8888);
is = client.getInputStream();
dis = new DataInputStream(is);
System.out.println(dis.readUTF());
dis.close();
is.close();
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
然後按照Socket工作流程,先啟動服務點監聽,執行結果:
啟動客戶端進行連線,執行結果:
連線成功後,接收到服務端發來的字串"hello!"
看一下服務端有什麼變化:
由於服務端是個死迴圈對8888
埠進行監聽,我們啟動客戶端多次看看服務端有什麼變化: