如何理解IP、端口號與計算機、操作系統、進程、線程的關系?
IP是計算機維度的。一個IP對應一個網卡。不過有的計算機可以有多個網卡。
端口號是線程維度的,用於不同計算機之間的線程進行通信。
為什么客戶端需要知道服務端的端口號,服務端不需要知道客戶端的端口號呢?
客戶端的端口是隨機產生的,服務端接受客戶端的請求的socket里面,帶有客戶端的端口號。
如下是服務端代碼:
import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class ServerSocketTest { public static void main(String[] args) { new Thread(new MyServerSocket(30000)).start(); new Thread(new MyServerSocket(40000)).start(); while (true){ } } } class MyServerSocket implements Runnable{ private int port; public MyServerSocket(int port){ this.port=port; } @Override public void run() { try { ServerSocket ss=new ServerSocket(port); while (true){ Socket socket = ss.accept(); OutputStream outputStream = socket.getOutputStream(); PrintStream printStream = new PrintStream(outputStream); printStream.println("hello current thread is "+Thread.currentThread().getName()); printStream.close(); socket.close(); } } catch (IOException e) { e.printStackTrace(); } } }
如下是客戶端代碼:(兩個客戶端)
import java.io.*; import java.net.Socket; public class ClientSocket { public static void main(String[] args) throws IOException { Socket socket = new Socket("127.0.0.1", 30000); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String line = bufferedReader.readLine(); System.out.println("來自服務器的數據"+line); bufferedReader.close(); socket.close(); } }
import java.io.*; import java.net.Socket; public class ClientSocket222 { public static void main(String[] args) throws IOException { Socket socket = new Socket("127.0.0.1", 40000); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String line = bufferedReader.readLine(); System.out.println("來自服務器的數據"+line); bufferedReader.close(); socket.close(); } }
在server打上斷點,可以看到客戶端請求的IP和端口號,客戶端的端口號57276是一個隨機的線程端口號。而服務端的30000端口號由於需要監聽客戶端的連接,所以客戶端需要知道這個端口號。

那么我客戶端可不可以指定端口呢?(既然服務端都可以指定端口來監聽,那么我客戶端應該也是可以的啊)
可以指定,但是不推薦指定,因為客戶度的socket一般用了就會關閉,不會始終占着這個端口,如果其他線程也用了這個端口,可能會報端口已經被占用,而且另外一個情況是,及時我同一份代碼,也可能是多線程,如果只有一個端口,那么多線程在這里就無用武之地了,因為也會報端口被占用。
下面給出客戶端指定端口號的java代碼:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; public class ClientSocket333 { public static void main(String[] args) throws IOException { Socket socket = new Socket(); //創建一個空的Socket SocketAddress socketAddress=new InetSocketAddress("127.0.0.1",6666); socket.bind(socketAddress); socket.connect(new InetSocketAddress("127.0.0.1",30000)); //真正的連接服務端 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String line = bufferedReader.readLine(); System.out.println("來自服務器的數據"+line); bufferedReader.close(); socket.close(); } }
在服務端打上斷點看效果,會發現接收到客戶端的socket的端口號就是6666了。

額外說一個關於開牆的知識,開牆開的是什么?網絡白名單和黑名單的兩種策略?(這部分知識有限,單純分享一點點)
進入企業后,只要是涉及到和外部系統交互,一定會涉及到開牆這個知識點,開牆開的是什么呢?
答案是IP+端口號。
如果你把防火牆關閉,比如我們安裝虛擬機之后,為了windows宿主機和虛擬機可以訪問通,一般把虛擬機的防火牆關閉,這樣一來虛擬機的所有端口都對windows宿主機開放了。
一般企業是怎么和外部系統交互的呢?
答案是防火牆+DMZ區+內網,或者通過認證的方式。

給大家留個問題思考(主要是這個問題我也不知道,哈哈哈)
瀏覽器訪問百度的時候,瀏覽器開啟了一個線程,使用了一個端口去訪問百度,這個端口暴露在了互聯網上,這個端口是不是就容易被攻擊?
