目錄
- 一、TCP互動以及Socket API呼叫
- 二、行程讀取資料的程序
- 三、java演示
- 服務端代碼
- 客戶端原始碼
- 執行結果
一、TCP互動以及Socket API呼叫
三次握手建立TCP以后開始傳輸資料,
Accept后對于服務端來說整個socket創建完畢,直接進入read狀態,read是一個阻塞呼叫,所謂阻塞是指服務器進入等待,直到read回傳,
read其實是的主要時間是等待資料ready:
- 客戶端發送后,有可能發送端的發送視窗已經滿了,需要等待,記為T1,
- 進入發送視窗后,TCP傳輸本身需要時間,T2,
- 接收端資料后從內核拷貝到用戶空間也需要時間,T3
所以read阻塞的時間至少需要T1+T2+T3,其中T1+T2的時間為等待資料的時間
二、行程讀取資料的程序
三、java演示
接下來用java原始碼來演示BIO的程序,為了看到效果特意在客戶端加入了兩次sleep來標識客戶端IO的時間,而服務端的read卻要一直等待阻塞在這個客戶端的IO上,
原始碼參考
服務端代碼
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SocketBioServer {
static SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress("localhost", 8080));
while (true) {
Socket socket = serverSocket.accept();
System.out.println(time() + "->accepted, begin to read......");
String result = readBytes(socket.getInputStream());
System.out.println(time() + "->" + result);
socket.close();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
static String readBytes(InputStream is) throws Exception {
long start = 0;
int total = 0;
long begin = System.currentTimeMillis();
int count = 0;
while ((count = is.read()) > -1) {//block,有資料寫入的時候才會回傳值,客戶端關閉后才會回傳-1
if (start == 0) {
start = System.currentTimeMillis();
}
total += count;
}
//讀完資料的時間
long end = System.currentTimeMillis();
return "wait=" + (start - begin) + "ms,read=" + (end - start) + "ms,total=" + total + "bs";
}
static String time() {
return sdf.format(new Date());
}
}
客戶端原始碼
import java.net.InetSocketAddress;
import java.net.Socket;
public class SocketBioClient {
public static void main(String[] args) {
try {
Socket s = new Socket();
s.connect(new InetSocketAddress("localhost", 8080));
Thread.sleep(5000);//模擬資料發送前的等待
s.getOutputStream().write(prepareBytes());
Thread.sleep(1000);//模擬寫入資料需要的時間
s.close();//關閉后客戶端才能回傳-1
} catch (Exception ex) {
ex.printStackTrace();
}
}
static byte[] prepareBytes() {
byte[] bytes = new byte[1024 * 1024 * 1];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = 1;
}
return bytes;
}
}
執行結果
23:03:14->accepted, begin to read......
23:03:20->wait=5005ms,read=1002ms,total=1048576bs
通過上述可以看到read一直阻塞等待客戶端的IO寫入,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/227721.html
標籤:其他
