关于主机多IP和服务端口绑定IP的研究
在网络编程中,经常需要在服务器里开一个端口,这里有一个问题,这个端口是开到哪个IP上面了,因为对于服务器来说经常是不止一个IP的,一个是127.0.0.1,一个是内网IP,比如192.168.1.3,一个是外网IP,比如211.19.56.39。对于开发着来说,经常会忽略绑定到具体某个IP上面,类似于下面的代码
ServerSocket serverSocket = new ServerSocket(8888); //serverSocket.bind(new InetSocketAddress(8888));
在这种情况下,一般服务器会把此端口绑定到0.0.0.0上面,即在所有IP上面都绑定,即能在每个ip上面收到请求。
但是对于一般服务器来说,都会有定制服务器IP的功能,比如对内网IP的访问会宽松些,放些公司内部的资料,而对于外网IP来说,访问会相对的严格,限制较多。基于这样的需求,我做了一些实验,如下。
首先 获得我电脑的所有ip和mac地址:
@Test public void testNetwork2() throws Exception{ Enumeration<NetworkInterface> interfaces=NetworkInterface.getNetworkInterfaces(); while(interfaces.hasMoreElements()){ NetworkInterface in= interfaces.nextElement(); System.out.println("mac:"+bytesToHexString(in.getHardwareAddress())); Enumeration<InetAddress> addrs=in.getInetAddresses(); while(addrs.hasMoreElements()){ InetAddress ia= addrs.nextElement(); if(ia instanceof Inet4Address){ System.out.println(ia.getHostAddress()); System.out.println("islookback:"+ia.isLoopbackAddress()); } } } } public static String bytesToHexString(byte[] src){ StringBuilder stringBuilder = new StringBuilder(""); if (src == null || src.length <= 0) { return null; } for (int i = 0; i < src.length; i++) { int v = src[i] & 0xFF; String hv = Integer.toHexString(v); if (hv.length() < 2) { stringBuilder.append(0); } stringBuilder.append(hv); } return stringBuilder.toString(); }
输出:
mac:null
127.0.0.1
islookback:true
mac:null
mac:null
mac:null
mac:null
mac:null
mac:null
mac:null
mac:null
mac:null
mac:00000000000000e0
mac:001aa027b7b6
10.11.2.63
islookback:false
mac:005056c00001
192.168.20.1
islookback:false
mac:null
mac:null
mac:null
mac:null
mac:null
mac:null
看到总共有3个ip 127.0.0.1 、10.11.2.63、192.168.20.1
实验一(在全网侦听):
ServerSocket serverSocket = new ServerSocket(); serverSocket.bind(new InetSocketAddress(8888)); serverSocket.accept();
在cmd里面输入netstat -ano -p TCP,输出如下:
协议 本地地址 外部地址 状态 PID
TCP 0.0.0.0:23 0.0.0.0:0 LISTENING 1936
TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 936
TCP 0.0.0.0:8888 0.0.0.0:0 LISTENING 484
TCP 0.0.0.0:49163 0.0.0.0:0 LISTENING 1264
TCP 0.0.0.0:55571 0.0.0.0:0 LISTENING 2768
TCP 10.11.2.63:139 0.0.0.0:0 LISTENING 4
TCP 127.0.0.1:8307 0.0.0.0:0 LISTENING 2596
TCP 192.168.20.1:139 0.0.0.0:0 LISTENING 4
此次可以用所有ip进行访问此端口
实验二(在127.0.0.1侦听):
ServerSocket serverSocket = new ServerSocket(); serverSocket.bind(new InetSocketAddress("127.0.0.1",8888)); serverSocket.accept();
在cmd里面输入netstat -ano -p TCP,输出如下:
协议 本地地址 外部地址 状态 PID
TCP 0.0.0.0:23 0.0.0.0:0 LISTENING 1936
TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 936
TCP 0.0.0.0:135 0.0.0.0:0 LISTENING 716
TCP 10.11.2.63:139 0.0.0.0:0 LISTENING 4
TCP 127.0.0.1:8307 0.0.0.0:0 LISTENING 2596
TCP 127.0.0.1:8888 0.0.0.0:0 LISTENING 3948
TCP 192.168.20.1:139 0.0.0.0:0 LISTENING 4
这个时候只能通过127.0.0.1来访问此端口,别的IP不可访问
实验三(在10.11.2.63侦听):
ServerSocket serverSocket = new ServerSocket(); serverSocket.bind(new InetSocketAddress("10.11.2.63",8888)); serverSocket.accept();
在cmd里面输入netstat -ano -p TCP,输出如下:
协议 本地地址 外部地址 状态 PID
TCP 0.0.0.0:23 0.0.0.0:0 LISTENING 1936
TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 936
TCP 0.0.0.0:135 0.0.0.0:0 LISTENING 716
TCP 10.11.2.63:139 0.0.0.0:0 LISTENING 4
TCP 10.11.2.63:8888 0.0.0.0:0 LISTENING 4324
TCP 127.0.0.1:8307 0.0.0.0:0 LISTENING 2596
TCP 192.168.20.1:139 0.0.0.0:0 LISTENING 4
这个时候只能通过 10.11.2.63来访问此端口,别的IP不可访问
实验四(在192.168.20.1侦听):
ServerSocket serverSocket = new ServerSocket(); serverSocket.bind(new InetSocketAddress("192.168.20.1",8888)); serverSocket.accept();
在cmd里面输入netstat -ano -p TCP,输出如下:
协议 本地地址 外部地址 状态 PID
TCP 0.0.0.0:23 0.0.0.0:0 LISTENING 1936
TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 936
TCP 10.11.2.63:139 0.0.0.0:0 LISTENING 4
TCP 127.0.0.1:8307 0.0.0.0:0 LISTENING 2596
TCP 192.168.20.1:139 0.0.0.0:0 LISTENING 4
TCP 192.168.20.1:8888 0.0.0.0:0 LISTENING 4652
这个时候只能通过 192.168.20.1来访问此端口,别的IP不可访问
实验五(在192.168.20.1和127.0.0.1同时侦听):
new Thread(){ public void run() { try { ServerSocket serverSocket = new ServerSocket(); serverSocket.bind(new InetSocketAddress("127.0.0.1",8888)); serverSocket.accept(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }; }.start(); ServerSocket serverSocket = new ServerSocket(); serverSocket.bind(new InetSocketAddress("192.168.20.1",8888)); serverSocket.accept();
在cmd里面输入netstat -ano -p TCP,输出如下:
协议 本地地址 外部地址 状态 PID
TCP 0.0.0.0:23 0.0.0.0:0 LISTENING 1936
TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 936
TCP 10.11.2.63:139 0.0.0.0:0 LISTENING 4
TCP 127.0.0.1:8307 0.0.0.0:0 LISTENING 2596
TCP 127.0.0.1:8888 0.0.0.0:0 LISTENING 1804
TCP 192.168.20.1:139 0.0.0.0:0 LISTENING 4
TCP 192.168.20.1:8888 0.0.0.0:0 LISTENING 1804
这个时候只能通过 192.168.20.1和127.0.0.1来访问此端口,别的IP不可访问
至此,大家应该对如何获取主机所有ip和端口在哪个ip上面绑定进一步了解了吧。下面贴上jdk的关于ip和端口的几个类图以及关系。