1. 程式人生 > >『黑馬程式設計師』---java--網路程式設計--TCP基礎

『黑馬程式設計師』---java--網路程式設計--TCP基礎

----------- android培訓java培訓、java學習型技術部落格、期待與您交流! ------------

TCP傳輸

✔Socket和ServerSocket

建立客戶端和服務端

✔建立連線後,通過Socket中的IO流進行資料的傳輸

✔關閉Socket

同樣,客戶端與伺服器端是兩個獨立的應用程式

TCP面向連線,傳輸可靠,連線後可以傳輸大量資料.

TCP分客戶端和服務端,客戶端對應的物件是Socket,服務端對應的物件是ServerSocket

服務端,一般常年開啟,供客戶端使用.


Socket  s = new  Socket(String host, int port);

客戶端通路建立產生網路(Socket).

此類實現客戶端套接字(也可以就叫“套接字”)。套接字是兩臺機器間通訊的端點。 

網路Socket流裡中既有輸入流也有輸出流..



需求:定義端點接受資料,並列印在控制檯上

服務端:

1,建立服務端的Socket服務,new ServerSocket()

並監聽一個埠

2,獲取連線過來的客戶端物件

通過ServerSocket的accept()方法,沒有連線就會等,所以這個方法是個阻塞的.

3,客戶端如果發過來資料,那麼服務端要使用對應客戶端物件,並獲取到該客戶端物件的讀取流來讀取發過來的資料並列印在控制檯上

4,關閉服務端(可選),通常大型伺服器都是72個小時常開不關的...

ServerSocket  ss = new  ServerSocket(int port);

服務端沒有流物件,服務端做的是,拿到客戶端的流物件.從而用客戶端的流物件進行傳輸.

accept()[]
          偵聽並接受到此套接字的連線。


服務端與客戶端資料傳輸圖示:


演示TCP的傳輸的客戶端和服務端的互訪

需求:客戶端給服務端傳送資料,服務端收到後,給客戶端反饋資訊

客戶端:

1,建立Socket服務,指定要連線的主機名和埠

2,獲取Socket流中的輸出流,將資料寫到該流中,通過網路傳送給服務端

3,獲取Socket流中的輸入流,將服務度昂反饋的資料獲取到,並列印

4,關閉客戶端資源


in.read()方法為,阻塞式方法,沒有資料,它就在等待.


通過阻塞方法,使程式有條不紊的執行.

Exercise:建立一個大小寫轉換服務

需求:建立一個文字轉換伺服器

客戶端給服務端傳送文字,服務端會將文字轉成大寫再返回給客戶端

而且客戶端可以不斷的想服務端進行文字轉換,當客戶端輸入over時便可結束

分析-客戶端:

既然是操作裝置上的資料,那麼就可以使用IO技術,並按照IO的操作規律來思考

源:鍵盤錄入

目的:網路裝置,網路輸出流

而且操作的是文字資料,可以選擇字元流

步驟:

1,建立服務

2,獲取鍵盤錄入

3,將資料發給服務端

4,獲取服務端返回的大寫資料

5,結束,關資源

都是文字資料,可以使用字元流進行操作,同時提高效率,加上緩衝區

注意,該例子容易出現的問題?

現象:客戶端和服務端都在莫名的等待,這其實是因為,客戶端和服務端都有阻塞式方法,這些方法沒有讀到結束標記,就會一直等待下去.導致的[記得緩衝區要時刻重新整理才能寫入資料]

解決:要手動建立結束標記,和即使重新整理



把寫入和讀取讀都放到while迴圈中,是因為,要達到.我寫入一行,服務端就要返回一行的目的

分析服務端::Socket讀取流 目的:Socket輸出流 因為,都是文字,可以裝飾,用字元流.


優化後的,程式碼:::::::::::::

//PrintStream-目的流----既能接受位元組流又能接受字元流,還能自動刷洗

import java.io.*;

import java.net.*;

class Client{

public static void main(String[] args)throws Exception{

Socket client=new Socket("127.0.0.1",10000);

//定義讀取鍵盤資料的流物件

BufferedReader buin=

new BufferedReader(new InputStreamReader(System.in));

//定義目的,將資料寫入到Socket輸出流,發給服務端,這裡用PrintWriter

PrintStream out=new PrintStream (client.getOutputStream(),true);

//定義一個Socket讀取流,讀取服務端返回的大寫資訊

BufferedReader bur=

new BufferedReader (new InputStreamReader (client.getInputStream()));

String line=null;

while((line=buin.readLine())!=null){

if("over".equals(line))

break;

out.println(line);

//讀取服務端返回的大寫資訊

System.out.println(bur.readLine());

}

//關閉客戶端

client.close();

//關閉鍵盤錄入

buin.close();

}

}

class TransServer{

public static void main(String[] args)throws Exception{

ServerSocket server=new ServerSocket(10000);

Socket client=server.accept();

System.out.println(client.getInetAddress().getHostAddress());

//讀取Socket讀取流中的資料

BufferedReader bur=

new BufferedReader(new InputStreamReader(client.getInputStream()));

//使用目的流,它即能接受字元流還能接受位元組流.[自動重新整理]

PrintStream ps=new PrintStream (client.getOutputStream(),true);

String line=null;

while((line=bur.readLine())!=null){

//一句話全搞定

ps.println(line.toUpperCase());

}

client.close();

}

}

小知識點:


Socket() 
          通過系統預設型別的 SocketImpl 建立未連線套接字

InetAddress封裝的是IP地址,SocketAddress封裝的是(IP 地址 埠號)

ServerSocket(int port, int backlog)
   利用指定的 backlog 建立伺服器套接字並將其繫結到指定的本地埠號。

backlog - 佇列的最大長度。 [能連線到伺服器的客戶端共同個數]線上人數