初級程式設計師不得不知道的東西
tcp的三次握手和四次揮手
tcp的十種狀態
Java中的基於tcp協議的socket通訊(服務端)
Tcp服務端(第一個版本)
/**
* Socket的服務端
*
*當前程式有弊端 只能為1個客戶端提供服務
*
*/
public class MyServerSocket01 {
/**
* 程式的執行入口
*
* @param args 傳遞的引數
*/
public static void main(String[] args) throws Exception {
//建立服務端的Socket物件
ServerSocket serverSocket = new ServerSocket();
//服務端繫結埠
serverSocket.bind(new InetSocketAddress(8899));
//監聽客戶端的連線(阻塞的方法),返回的是當前連線到伺服器的客戶端的物件
Socket socket = serverSocket.accept();
System.out.println("有客戶端" + socket.getRemoteSocketAddress() + "連線到伺服器了.....");
InputStream inputStream = socket.getInputStream();
//讀資料
byte[] buf = new byte[2];
int len;
//呼叫read方法返回阻塞,當沒有資料時會阻塞,並不會返回-1
while ((len = inputStream.read(buf)) != -1) {
String str = new String(buf, 0, len);
System.out.println(str);
}
}
}
Tcp服務端(第二個版本)
/**
* Socket的服務端
* 當前程式有弊端 只能為一個客戶端提供服務,只不過一個客戶端斷開連線之後其他的客戶端才能進來
*/
public class MyServerSocket02 {
/**
* 程式的執行入口
*
* @param args 傳遞的引數
*/
public static void main(String[] args) throws Exception {
//建立服務端的Socket物件
ServerSocket serverSocket = new ServerSocket();
//服務端繫結埠
serverSocket.bind(new InetSocketAddress(8899));
while (true) {
//監聽客戶端的連線(阻塞的方法),返回的是當前連線到伺服器的客戶端的物件
Socket socket = serverSocket.accept();
System.out.println("有客戶端" + socket.getRemoteSocketAddress() + "連線到伺服器了.....");
InputStream inputStream = socket.getInputStream();
//讀資料
byte[] buf = new byte[2];
int len;
//呼叫read方法返回阻塞,當沒有資料時會阻塞,並不會返回-1
while ((len = inputStream.read(buf)) != -1) {
String str = new String(buf, 0, len);
System.out.println(str);
}
}
}
}
Tcp服務端(第三個版本)
/**
* Socket的服務端
* 當前程式有弊端 每次一個客戶端進來之後都會建立一個執行緒去處理連線任務,但有大量的客戶端連線到伺服器的話就會有大量的執行緒建立,執行緒的建立和上下文的切換也是非常耗費時間和資源的
*/
public class MyServerSocket02 {
/**
* 程式的執行入口
*
* @param args 傳遞的引數
*/
public static void main(String[] args) throws Exception {
//建立服務端的Socket物件
ServerSocket serverSocket = new ServerSocket();
//服務端繫結埠
serverSocket.bind(new InetSocketAddress(8899));
while (true) {
//監聽客戶端的連線(阻塞的方法),返回的是當前連線到伺服器的客戶端的物件
Socket socket = serverSocket.accept();
//每次有新的客戶端連線到伺服器之後都會啟動執行緒來執行
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("有客戶端" + socket.getRemoteSocketAddress() + "連線到伺服器了.....");
InputStream inputStream = null;
try {
inputStream = socket.getInputStream();
//讀資料
byte[] buf = new byte[2];
int len;
//呼叫read方法返回阻塞,當沒有資料時會阻塞,並不會返回-1
while ((len = inputStream.read(buf)) != -1) {
String str = new String(buf, 0, len);
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
}
Tcp服務端(第四個版本)
/**
* Socket的服務端
* 當前程式有弊端 有兩個阻塞 accept read,其中accept我們就無法解決,但是read阻塞可以解決的(NIO)
*/
public class MyServerSocket04 {
/**
* 程式的執行入口
*
* @param args 傳遞的引數
*/
public static void main(String[] args) throws Exception {
//建立執行緒池物件(執行緒池的大小是本機的cpu可用的核數)
ExecutorService threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
//建立服務端的Socket物件
ServerSocket serverSocket = new ServerSocket();
//服務端繫結埠
serverSocket.bind(new InetSocketAddress(8899));
while (true) {
//監聽客戶端的連線(阻塞的方法),返回的是當前連線到伺服器的客戶端的物件
Socket socket = serverSocket.accept();
//每次有新的客戶端連線到伺服器之後都會啟動執行緒來執行
threadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println("有客戶端" + socket.getRemoteSocketAddress() + "連線到伺服器了.....");
InputStream inputStream = null;
try {
inputStream = socket.getInputStream();
//讀資料
byte[] buf = new byte[2];
int len;
//呼叫read方法返回阻塞,當沒有資料時會阻塞,並不會返回-1
while ((len = inputStream.read(buf)) != -1) {
String str = new String(buf, 0, len);
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
}