通信是分布式架構的一個基本問題, 通信是基於通信協議, 通過網絡IO來實現的, 基本的通信協議有TCP,HTTP,UDP等, Java的IO分為BIO,NIO,AIO等, java領域有很多支持通信的技術, 如RMI,MINA,JMS等.
網絡協議
-
TCP/IP:
五層模型: 基於OSI七層模型. 包含: 應用層,傳輸層(TCP/IP協議),網絡層(ICMP,IGMP),鏈路層,物理層. OSI還包含表現層,會話層.
三次握手:
Dos攻擊就是在第三步發生, 發送大量連接請求, 使網絡處在半連接狀態. server端的連接未完成, 導致阻塞.
四次揮手:
TCP協議是全雙工的, 全雙工是雙方可以相互發起通信, 數據可以往兩個方向傳輸; 半雙工是某個階段只能一方傳輸; 單工是只能一方往另一方傳輸數據.
-
UDP/IP:
阻塞的概念
了解阻塞, 就首先需要了解TCP傳輸協議的緩存區概念.
應用層發送數據的時候, 首先數據會暫存到傳輸層的緩存區.
數據傳輸的時候有個滑動窗口的概念, 窗口的大小可以控制, 這樣可以保證接收方緩存區不夠大導致緩存溢出. 窗口的數據全部發送且接收方確認收到后才可以向前繼續滑動.
發送方和接收方均有緩存區, 當緩存區滿(或空, 分別對應寫和讀)的時候就會發生阻塞, 必須等緩存區有足夠空間容納更多數據的時候才能繼續發送或接收.
阻塞分為BIO(同步阻塞),NIO(同步非阻塞, 同路復用技術,netty等使用這種方式),AIO(異步非阻塞, java7開始)
阻塞和非阻塞, 同步和異步分開理解比較好.阻塞和非阻塞是針對調用者, 阻塞是緩沖區讀寫沒有數據的時候線程等待, 非阻塞是緩沖區讀寫沒有數據時立即返回, 線程去做其他的事情; 同步和異步是針對被調用者, 被調用者處理時不返回時, 調用者需要等待結果是同步, 被調用者立即返回,同時做處理時異步.
Java 網絡通信
TCP Socket通信
// 服務端
public class SocketServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
try{
serverSocket = new ServerSocket(8888);
Socket socket= serverSocket.accept();
// 緩沖區讀取
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println(reader.readLine());
reader.close();
socket.close();
}catch (Exception e){
}finally {
if(serverSocket!=null){
serverSocket.close();
}
}
}
}
//客戶端
public class SocketClient {
public static void main(String[] args) throws IOException {
try{
Socket socket = new Socket("localhost",8888);
PrintWriter writer = new PrintWriter(socket.getOutputStream(),true);
writer.println("this is a message from client");
writer.close();
socket.close();
}catch (Exception e){
}finally {
}
}
}
Multicast 多播, 使用UDP協議
// 服務端
public class MulticastServer {
public static void main(String[] args) throws IOException, InterruptedException {
// 多播必須是224網段
InetAddress group = InetAddress.getByName("224.7.8.9");
MulticastSocket socket = new MulticastSocket();
for (int i = 0; i < 10; i++) {
String data = "multcast"+i;
byte[] bytes = data.getBytes();
socket.send(new DatagramPacket(bytes,bytes.length,group,8888));
TimeUnit.SECONDS.sleep(2);
}
}
}
// 客戶端
public class MulticastClient {
public static void main(String[] args) throws IOException, InterruptedException {
// 多播必須是224網段
InetAddress group = InetAddress.getByName("224.7.8.9");
MulticastSocket socket = new MulticastSocket(8888);
socket.joinGroup(group);
byte[] buf = new byte[32];
while (true){
DatagramPacket packet = new DatagramPacket(buf,buf.length);
socket.receive(packet);
String reveived = new String(packet.getData());
System.out.println("received:"+reveived);
}
}
}