forked from kangjianwei/LearningJDK
-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathInetAddress.java
1918 lines (1708 loc) · 75.6 KB
/
InetAddress.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.net;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectInputStream.GetField;
import java.io.ObjectOutputStream;
import java.io.ObjectOutputStream.PutField;
import java.io.ObjectStreamException;
import java.io.ObjectStreamField;
import java.io.Serializable;
import java.lang.annotation.Native;
import java.security.AccessController;
import java.util.ArrayList;
import java.util.NavigableSet;
import java.util.Objects;
import java.util.Scanner;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.atomic.AtomicLong;
import jdk.internal.misc.JavaNetInetAddressAccess;
import jdk.internal.misc.SharedSecrets;
import sun.net.InetAddressCachePolicy;
import sun.net.util.IPAddressUtil;
import sun.security.action.GetPropertyAction;
/**
* This class represents an Internet Protocol (IP) address.
*
* <p> An IP address is either a 32-bit or 128-bit unsigned number
* used by IP, a lower-level protocol on which protocols like UDP and
* TCP are built. The IP address architecture is defined by <a
* href="http://www.ietf.org/rfc/rfc790.txt"><i>RFC 790:
* Assigned Numbers</i></a>, <a
* href="http://www.ietf.org/rfc/rfc1918.txt"> <i>RFC 1918:
* Address Allocation for Private Internets</i></a>, <a
* href="http://www.ietf.org/rfc/rfc2365.txt"><i>RFC 2365:
* Administratively Scoped IP Multicast</i></a>, and <a
* href="http://www.ietf.org/rfc/rfc2373.txt"><i>RFC 2373: IP
* Version 6 Addressing Architecture</i></a>. An instance of an
* InetAddress consists of an IP address and possibly its
* corresponding host name (depending on whether it is constructed
* with a host name or whether it has already done reverse host name
* resolution).
*
* <h3> Address types </h3>
*
* <table class="striped" style="margin-left:2em">
* <caption style="display:none">Description of unicast and multicast address types</caption>
* <thead>
* <tr><th scope="col">Address Type</th><th scope="col">Description</th></tr>
* </thead>
* <tbody>
* <tr><th scope="row" style="vertical-align:top">unicast</th>
* <td>An identifier for a single interface. A packet sent to
* a unicast address is delivered to the interface identified by
* that address.
*
* <p> The Unspecified Address -- Also called anylocal or wildcard
* address. It must never be assigned to any node. It indicates the
* absence of an address. One example of its use is as the target of
* bind, which allows a server to accept a client connection on any
* interface, in case the server host has multiple interfaces.
*
* <p> The <i>unspecified</i> address must not be used as
* the destination address of an IP packet.
*
* <p> The <i>Loopback</i> Addresses -- This is the address
* assigned to the loopback interface. Anything sent to this
* IP address loops around and becomes IP input on the local
* host. This address is often used when testing a
* client.</td></tr>
* <tr><th scope="row" style="vertical-align:top">multicast</th>
* <td>An identifier for a set of interfaces (typically belonging
* to different nodes). A packet sent to a multicast address is
* delivered to all interfaces identified by that address.</td></tr>
* </tbody>
* </table>
*
* <h4> IP address scope </h4>
*
* <p> <i>Link-local</i> addresses are designed to be used for addressing
* on a single link for purposes such as auto-address configuration,
* neighbor discovery, or when no routers are present.
*
* <p> <i>Site-local</i> addresses are designed to be used for addressing
* inside of a site without the need for a global prefix.
*
* <p> <i>Global</i> addresses are unique across the internet.
*
* <h4> Textual representation of IP addresses </h4>
*
* The textual representation of an IP address is address family specific.
*
* <p>
*
* For IPv4 address format, please refer to <A
* HREF="Inet4Address.html#format">Inet4Address#format</A>; For IPv6
* address format, please refer to <A
* HREF="Inet6Address.html#format">Inet6Address#format</A>.
*
* <P>There is a <a href="doc-files/net-properties.html#Ipv4IPv6">couple of
* System Properties</a> affecting how IPv4 and IPv6 addresses are used.</P>
*
* <h4> Host Name Resolution </h4>
*
* Host name-to-IP address <i>resolution</i> is accomplished through
* the use of a combination of local machine configuration information
* and network naming services such as the Domain Name System (DNS)
* and Network Information Service(NIS). The particular naming
* services(s) being used is by default the local machine configured
* one. For any host name, its corresponding IP address is returned.
*
* <p> <i>Reverse name resolution</i> means that for any IP address,
* the host associated with the IP address is returned.
*
* <p> The InetAddress class provides methods to resolve host names to
* their IP addresses and vice versa.
*
* <h4> InetAddress Caching </h4>
*
* The InetAddress class has a cache to store successful as well as
* unsuccessful host name resolutions.
*
* <p> By default, when a security manager is installed, in order to
* protect against DNS spoofing attacks,
* the result of positive host name resolutions are
* cached forever. When a security manager is not installed, the default
* behavior is to cache entries for a finite (implementation dependent)
* period of time. The result of unsuccessful host
* name resolution is cached for a very short period of time (10
* seconds) to improve performance.
*
* <p> If the default behavior is not desired, then a Java security property
* can be set to a different Time-to-live (TTL) value for positive
* caching. Likewise, a system admin can configure a different
* negative caching TTL value when needed.
*
* <p> Two Java security properties control the TTL values used for
* positive and negative host name resolution caching:
*
* <dl style="margin-left:2em">
* <dt><b>networkaddress.cache.ttl</b></dt>
* <dd>Indicates the caching policy for successful name lookups from
* the name service. The value is specified as an integer to indicate
* the number of seconds to cache the successful lookup. The default
* setting is to cache for an implementation specific period of time.
* <p>
* A value of -1 indicates "cache forever".
* </dd>
* <dt><b>networkaddress.cache.negative.ttl</b> (default: 10)</dt>
* <dd>Indicates the caching policy for un-successful name lookups
* from the name service. The value is specified as an integer to
* indicate the number of seconds to cache the failure for
* un-successful lookups.
* <p>
* A value of 0 indicates "never cache".
* A value of -1 indicates "cache forever".
* </dd>
* </dl>
*
* @author Chris Warth
* @see java.net.InetAddress#getByAddress(byte[])
* @see java.net.InetAddress#getByAddress(java.lang.String, byte[])
* @see java.net.InetAddress#getAllByName(java.lang.String)
* @see java.net.InetAddress#getByName(java.lang.String)
* @see java.net.InetAddress#getLocalHost()
* @since 1.0
*/
/*
* InetAddress代表一个IP地址,包括IP4和IP6。
*
* IP地址由一串无符号字节组成,IP4是用点号分割的4个无符号字节(共计32位),IP6是用冒号分割的8个区块,每个区块是4个十六进制数字(共计128位)。
*/
public class InetAddress implements Serializable {
@Native
static final int PREFER_IPV4_VALUE = 0;
@Native
static final int PREFER_IPV6_VALUE = 1;
@Native
static final int PREFER_SYSTEM_VALUE = 2;
/**
* Specify the address family: Internet Protocol, Version 4
*
* @since 1.4
*/
@Native
static final int IPv4 = 1;
/**
* Specify the address family: Internet Protocol, Version 6
*
* @since 1.4
*/
@Native
static final int IPv6 = 2;
/** Specify address family preference */
// 标记使用IP4地址还是IP6地址
static transient final int preferIPv6Address;
// 用来映射主机地址/名称,以及判断网络地址的可用性
static final InetAddressImpl impl;
/** Used to store the serializable fields of InetAddress */
// 存储IP4地址的可序列化字段
final transient InetAddressHolder holder;
/** Used to store the name service provider */
// IP-域名映射服务
private static transient NameService nameService = null;
/** mapping from host name to Addresses - either NameServiceAddresses (while still being looked-up by NameService(s)) or CachedAddresses when cached */
// 如果不使用缓存,则存储NameServiceAddresses,如果使用缓存,则替换为CachedAddresses
private static final ConcurrentMap<String, Addresses> cache = new ConcurrentHashMap<>();
/** CachedAddresses that have to expire are kept ordered in this NavigableSet which is scanned on each access */
// 缓存带有有效期的查询出来的网络地址(为了快速筛选出过期的缓存)
private static final NavigableSet<CachedAddresses> expirySet = new ConcurrentSkipListSet<>();
// 缓存本地主机名称和地址
private static volatile CachedLocalHost cachedLocalHost;
/**
* Used to store the best available hostname.
* Lazily initialized via a data race; safe because Strings are immutable.
*/
// 当前网络地址的主机名
private transient String canonicalHostName = null;
/* Load net library into runtime, and perform initializations */
static {
String str = AccessController.doPrivileged(new GetPropertyAction("java.net.preferIPv6Addresses"));
if(str == null) {
// 默认使用IP4地址
preferIPv6Address = PREFER_IPV4_VALUE;
} else if(str.equalsIgnoreCase("true")) {
preferIPv6Address = PREFER_IPV6_VALUE;
} else if(str.equalsIgnoreCase("false")) {
preferIPv6Address = PREFER_IPV4_VALUE;
} else if(str.equalsIgnoreCase("system")) {
preferIPv6Address = PREFER_SYSTEM_VALUE;
} else {
preferIPv6Address = PREFER_IPV4_VALUE;
}
AccessController.doPrivileged(new java.security.PrivilegedAction<>() {
public Void run() {
System.loadLibrary("net");
return null;
}
});
SharedSecrets.setJavaNetInetAddressAccess(new JavaNetInetAddressAccess() {
public String getOriginalHostName(InetAddress ia) {
return ia.holder.getOriginalHostName();
}
public InetAddress getByName(String hostName, InetAddress hostAddress) throws UnknownHostException {
return InetAddress.getByName(hostName, hostAddress);
}
});
init();
}
static {
// 创建InetAddressImpl的实现类(分为IP4和IP6两种)
impl = InetAddressImplFactory.create();
// 构建一个IP-域名映射服务
nameService = createNameService();
}
/*▼ 构造器 ████████████████████████████████████████████████████████████████████████████████┓ */
/**
* Constructor for the Socket.accept() method.
* This creates an empty InetAddress, which is filled in by
* the accept() method. This InetAddress, however, is not
* put in the address cache, since it is not created by name.
*/
InetAddress() {
holder = new InetAddressHolder();
}
/*▲ 构造器 ████████████████████████████████████████████████████████████████████████████████┛ */
/*▼ 工厂方法 ████████████████████████████████████████████████████████████████████████████████┓ */
/**
* Returns an {@code InetAddress} object given the raw IP address .
* The argument is in network byte order: the highest order
* byte of the address is in {@code getAddress()[0]}.
*
* <p> This method doesn't block, i.e. no reverse name service lookup
* is performed.
*
* <p> IPv4 address byte array must be 4 bytes long and IPv6 byte array
* must be 16 bytes long
*
* @param addr the raw IP address in network byte order
*
* @return an InetAddress object created from the raw IP address.
*
* @throws UnknownHostException if IP address is of illegal length
* @since 1.4
*/
// 用给定主机地址创建一个InetAddress实例
public static InetAddress getByAddress(byte[] addr) throws UnknownHostException {
return getByAddress(null, addr);
}
/**
* Creates an InetAddress based on the provided host name and IP address.
* No name service is checked for the validity of the address.
*
* <p> The host name can either be a machine name, such as
* "{@code java.sun.com}", or a textual representation of its IP
* address.
* <p> No validity checking is done on the host name either.
*
* <p> If addr specifies an IPv4 address an instance of Inet4Address
* will be returned; otherwise, an instance of Inet6Address
* will be returned.
*
* <p> IPv4 address byte array must be 4 bytes long and IPv6 byte array
* must be 16 bytes long
*
* @param host the specified host
* @param addr the raw IP address in network byte order
*
* @return an InetAddress object created from the raw IP address.
*
* @throws UnknownHostException if IP address is of illegal length
* @since 1.4
*/
// 用给定主机名称与主机地址创建一个InetAddress实例
public static InetAddress getByAddress(String host, byte[] addr) throws UnknownHostException {
// 去掉host外层的[]
if(host != null && host.length()>0 && host.charAt(0) == '[') {
if(host.charAt(host.length() - 1) == ']') {
host = host.substring(1, host.length() - 1);
}
}
if(addr != null) {
if(addr.length == Inet4Address.INADDRSZ) {
return new Inet4Address(host, addr);
} else if(addr.length == Inet6Address.INADDRSZ) {
// 将IP6地址转换为IP4地址,转换失败则返回null
byte[] newAddr = IPAddressUtil.convertFromIPv4MappedAddress(addr);
if(newAddr != null) {
// 本质是IP4地址
return new Inet4Address(host, newAddr);
} else {
// 确实是IP6地址
return new Inet6Address(host, addr);
}
}
}
throw new UnknownHostException("addr is of illegal length");
}
/**
* Returns the loopback address.
* <p>
* The InetAddress returned will represent the IPv4
* loopback address, 127.0.0.1, or the IPv6 loopback
* address, ::1. The IPv4 loopback address returned
* is only one of many in the form 127.*.*.*
*
* @return the InetAddress loopback instance.
*
* @since 1.7
*/
// 返回本地回环地址
public static InetAddress getLoopbackAddress() {
return impl.loopbackAddress();
}
/**
* Returns the address of the local host. This is achieved by retrieving
* the name of the host from the system, then resolving that name into
* an {@code InetAddress}.
*
* <P>Note: The resolved address may be cached for a short period of time.
* </P>
*
* <p>If there is a security manager, its
* {@code checkConnect} method is called
* with the local host name and {@code -1}
* as its arguments to see if the operation is allowed.
* If the operation is not allowed, an InetAddress representing
* the loopback address is returned.
*
* @return the address of the local host.
*
* @throws UnknownHostException if the local host name could not
* be resolved into an address.
* @see SecurityManager#checkConnect
* @see java.net.InetAddress#getByName(java.lang.String)
*/
// 返回本地主机地址
public static InetAddress getLocalHost() throws UnknownHostException {
SecurityManager security = System.getSecurityManager();
try {
// is cached data still valid?
CachedLocalHost clh = cachedLocalHost;
// 缓存未过时的话,直接从缓存中获取
if(clh != null && (clh.expiryTime - System.nanoTime()) >= 0L) {
if(security != null) {
security.checkConnect(clh.host, -1);
}
return clh.addr;
}
// 获取本地主机名称
String local = impl.getLocalHostName();
if(security != null) {
security.checkConnect(local, -1);
}
InetAddress localAddr;
// shortcut for "localhost" host name
if(local.equals("localhost")) {
// 获取本地环回地址
localAddr = impl.loopbackAddress();
} else {
// call getAllByName0 without security checks and without using cached data
try {
localAddr = getAllByName0(local, null, false, false)[0];
} catch(UnknownHostException uhe) {
// Rethrow with a more informative error message.
UnknownHostException uhe2 = new UnknownHostException(local + ": " + uhe.getMessage());
uhe2.initCause(uhe);
throw uhe2;
}
}
// 将本地主机名称和地址加入到缓存中
cachedLocalHost = new CachedLocalHost(local, localAddr);
return localAddr;
} catch(SecurityException e) {
return impl.loopbackAddress();
}
}
/**
* Determines the IP address of a host, given the host's name.
*
* <p> The host name can either be a machine name, such as
* "{@code java.sun.com}", or a textual representation of its
* IP address. If a literal IP address is supplied, only the
* validity of the address format is checked.
*
* <p> For {@code host} specified in literal IPv6 address,
* either the form defined in RFC 2732 or the literal IPv6 address
* format defined in RFC 2373 is accepted. IPv6 scoped addresses are also
* supported. See <a href="Inet6Address.html#scoped">here</a> for a description of IPv6
* scoped addresses.
*
* <p> If the host is {@code null} or {@code host.length()} is equal
* to zero, then an {@code InetAddress} representing an address of the
* loopback interface is returned.
* See <a href="http://www.ietf.org/rfc/rfc3330.txt">RFC 3330</a>
* section 2 and <a href="http://www.ietf.org/rfc/rfc2373.txt">RFC 2373</a>
* section 2.5.3.
*
* <p> If there is a security manager, and {@code host} is not {@code null}
* or {@code host.length() } is not equal to zero, the security manager's
* {@code checkConnect} method is called with the hostname and {@code -1}
* as its arguments to determine if the operation is allowed.
*
* @param host the specified host, or {@code null}.
*
* @return an IP address for the given host name.
*
* @throws UnknownHostException if no IP address for the
* {@code host} could be found, or if a scope_id was specified
* for a global IPv6 address.
* @throws SecurityException if a security manager exists
* and its checkConnect method doesn't allow the operation
*/
// ▶ 1-1-1-1 根据主机名称或主机IP,创建/查找其对应的InetAddress实例(有多个实例时只选择第一个)
public static InetAddress getByName(String host) throws UnknownHostException {
return InetAddress.getAllByName(host)[0];
}
/**
* Given the name of a host, returns an array of its IP addresses,
* based on the configured name service on the system.
*
* <p> The host name can either be a machine name, such as
* "{@code java.sun.com}", or a textual representation of its IP
* address. If a literal IP address is supplied, only the
* validity of the address format is checked.
*
* <p> For {@code host} specified in <i>literal IPv6 address</i>,
* either the form defined in RFC 2732 or the literal IPv6 address
* format defined in RFC 2373 is accepted. A literal IPv6 address may
* also be qualified by appending a scoped zone identifier or scope_id.
* The syntax and usage of scope_ids is described
* <a href="Inet6Address.html#scoped">here</a>.
*
* <p> If the host is {@code null} or {@code host.length()} is equal
* to zero, then an {@code InetAddress} representing an address of the
* loopback interface is returned.
* See <a href="http://www.ietf.org/rfc/rfc3330.txt">RFC 3330</a>
* section 2 and <a href="http://www.ietf.org/rfc/rfc2373.txt">RFC 2373</a>
* section 2.5.3. </p>
*
* <p> If there is a security manager, and {@code host} is not {@code null}
* or {@code host.length() } is not equal to zero, the security manager's
* {@code checkConnect} method is called with the hostname and {@code -1}
* as its arguments to determine if the operation is allowed.
*
* @param host the name of the host, or {@code null}.
*
* @return an array of all the IP addresses for a given host name.
*
* @throws UnknownHostException if no IP address for the
* {@code host} could be found, or if a scope_id was specified
* for a global IPv6 address.
* @throws SecurityException if a security manager exists and its
* {@code checkConnect} method doesn't allow the operation.
* @see SecurityManager#checkConnect
*/
// ▶ 1-1-1 根据主机名称或主机IP,创建/查找其对应的InetAddress实例
public static InetAddress[] getAllByName(String host) throws UnknownHostException {
return getAllByName(host, null);
}
/** called from deployment cache manager */
// ▶ 1-1-2 根据主机名称或主机IP,创建/查找其对应的InetAddress实例(有多个实例时只选择第一个)
private static InetAddress getByName(String host, InetAddress reqAddr) throws UnknownHostException {
return InetAddress.getAllByName(host, reqAddr)[0];
}
// ▶ 1-2-1 根据主机名称,创建/查找其对应的InetAddress实例
private static InetAddress[] getAllByName0(String host) throws UnknownHostException {
return getAllByName0(host, true);
}
// ▶ 1-1 根据主机名称或主机IP,创建/查找其对应的InetAddress实例
private static InetAddress[] getAllByName(String host, InetAddress reqAddr) throws UnknownHostException {
// host为空,则使用本地环回地址
if(host == null || host.length() == 0) {
InetAddress[] ret = new InetAddress[1];
ret[0] = impl.loopbackAddress();
return ret;
}
boolean ipv6Expected = false;
// 去掉host外层的[]
if(host.charAt(0) == '[') {
// This is supposed to be an IPv6 literal
if(host.length()>2 && host.charAt(host.length() - 1) == ']') {
host = host.substring(1, host.length() - 1);
ipv6Expected = true;
} else {
// This was supposed to be a IPv6 address, but it's not!
throw new UnknownHostException(host + ": invalid IPv6 address");
}
}
// 如果host是IP地址,则不需要进行查找
if(Character.digit(host.charAt(0), 16) != -1 || (host.charAt(0) == ':')) {
byte[] addr = null;
int numericZone = -1;
String ifname = null;
// 将文本形式的IP4地址转换为二进制形式
addr = IPAddressUtil.textToNumericFormatV4(host);
if(addr == null) {
// This is supposed to be an IPv6 literal
// Check if a numeric or string zone id is present
int pos;
if((pos = host.indexOf('%')) != -1) {
numericZone = checkNumericZone(host);
if(numericZone == -1) { /* remainder of string must be an ifname */
ifname = host.substring(pos + 1);
}
}
// 将文本形式的IP6地址转换为二进制形式
if((addr = IPAddressUtil.textToNumericFormatV6(host)) == null && host.contains(":")) {
throw new UnknownHostException(host + ": invalid IPv6 address");
}
} else if(ipv6Expected) {
// Means an IPv4 litteral between brackets!
throw new UnknownHostException("[" + host + "]");
}
InetAddress[] ret = new InetAddress[1];
if(addr != null) {
if(addr.length == Inet4Address.INADDRSZ) {
ret[0] = new Inet4Address(null, addr);
} else {
if(ifname != null) {
ret[0] = new Inet6Address(null, addr, ifname);
} else {
ret[0] = new Inet6Address(null, addr, numericZone);
}
}
return ret;
}
} else if(ipv6Expected) {
// We were expecting an IPv6 Litteral, but got something else
throw new UnknownHostException("[" + host + "]");
}
return getAllByName0(host, reqAddr, true, true);
}
/**
* package private so SocketPermission can call it
*/
// ▶ 1-2 根据主机名称,创建/查找其对应的InetAddress实例
static InetAddress[] getAllByName0(String host, boolean check) throws UnknownHostException {
return getAllByName0(host, null, check, true);
}
/**
* Designated lookup method.
*
* @param host host name to look up
* @param reqAddr requested address to be the 1st in returned array
* @param check perform security check
* @param useCache use cached value if not expired else always perform name service lookup (and cache the result)
*
* @return array of InetAddress(es)
*
* @throws UnknownHostException if host name is not found
*/
/*
* ▶ 1
*
* 根据主机名称,创建/查找其对应的InetAddress实例
*
* 如果给定的是主机名称,则需要查询其对应的IP地址,一个主机名称可能对应多个主机地址,
* 此时,返回结果将是一个InetAddress列表,
*
* reqAddr代表预期的InetAddress,如果最终的InetAddress列表中包含reqAddr,则将其调整到列表的首位
*/
private static InetAddress[] getAllByName0(String host, InetAddress reqAddr, boolean check, boolean useCache) throws UnknownHostException {
/* If it gets here it is presumed to be a hostname */
// make sure the connection to the host is allowed, before we give out a hostname
if(check) {
SecurityManager security = System.getSecurityManager();
if(security != null) {
security.checkConnect(host, -1);
}
}
// remove expired addresses from cache - expirySet keeps them ordered by expiry time so we only need to iterate the prefix of the NavigableSet...
long now = System.nanoTime();
// 从expirySet中查找匹配的缓存
for(CachedAddresses caddrs : expirySet) {
/*
* compare difference of time instants rather than time instants directly, to avoid possible overflow.
* (see System.nanoTime() recommendations...)
*/
// 顺路清除过期缓存
if((caddrs.expiryTime - now)<0L) {
// ConcurrentSkipListSet uses weakly consistent iterator, so removing while iterating is OK...
if(expirySet.remove(caddrs)) {
// ... remove from cache
cache.remove(caddrs.host, caddrs);
}
} else {
// we encountered 1st element that expires in future
break;
}
}
// look-up or remove from cache
Addresses addrs;
// 如果需要使用缓存
if(useCache) {
// 从缓存池中获取元素
addrs = cache.get(host);
} else {
// 从缓存池中移除元素
addrs = cache.remove(host);
// 如果成功移除了相应的元素
if(addrs != null) {
if(addrs instanceof CachedAddresses) {
// try removing from expirySet too if CachedAddresses
expirySet.remove(addrs);
}
addrs = null;
}
}
if(addrs == null) {
/* create a NameServiceAddresses instance which will look up the name service and install it within cache... */
// 创建一个缓存元素
addrs = new NameServiceAddresses(host, reqAddr);
// 将缓存元素加入到缓存池中
Addresses oldAddrs = cache.putIfAbsent(host, addrs);
// 缓存中已经存在该host(可能被别的线程抢先缓存了)
if(oldAddrs != null) {
// 更新addrs为当前缓存中的Addresses
addrs = oldAddrs;
}
}
// ask Addresses to get an array of InetAddress(es) and clone it
return addrs.get().clone();
}
// 通过IP-域名映射服务,查询出host对应的网络地址列表。如果reqAddr也在其中,将其设置到列表首位。
static InetAddress[] getAddressesFromNameService(String host, InetAddress reqAddr) throws UnknownHostException {
InetAddress[] addresses = null;
UnknownHostException ex = null;
try {
// 将主机名称或主机地址映射为InetAddress实例
addresses = nameService.lookupAllHostAddr(host);
} catch(UnknownHostException uhe) {
if(host.equalsIgnoreCase("localhost")) {
addresses = new InetAddress[]{impl.loopbackAddress()};
} else {
ex = uhe;
}
}
if(addresses == null) {
throw ex == null ? new UnknownHostException(host) : ex;
}
// 如果需要的话,将reqAddr调整到addresses首位
if(reqAddr != null && addresses.length>1 && !addresses[0].equals(reqAddr)) {
// Find it?
int i = 1;
for(; i<addresses.length; i++) {
if(addresses[i].equals(reqAddr)) {
break;
}
}
// 将reqAddr插入到addresses首位
if(i<addresses.length) {
InetAddress tmp, tmp2 = reqAddr;
for(int j = 0; j<i; j++) {
tmp = addresses[j];
addresses[j] = tmp2;
tmp2 = tmp;
}
addresses[i] = tmp2;
}
}
return addresses;
}
/**
* Returns the InetAddress representing anyLocalAddress (typically 0.0.0.0 or ::0)
*/
// 获取通配地址
static InetAddress anyLocalAddress() {
return impl.anyLocalAddress();
}
/*▲ 工厂方法 ████████████████████████████████████████████████████████████████████████████████┛ */
/*▼ 属性 ████████████████████████████████████████████████████████████████████████████████┓ */
/**
* Test whether that address is reachable. Best effort is made by the
* implementation to try to reach the host, but firewalls and server
* configuration may block requests resulting in a unreachable status
* while some specific ports may be accessible.
* A typical implementation will use ICMP ECHO REQUESTs if the
* privilege can be obtained, otherwise it will try to establish
* a TCP connection on port 7 (Echo) of the destination host.
* <p>
* The timeout value, in milliseconds, indicates the maximum amount of time
* the try should take. If the operation times out before getting an
* answer, the host is deemed unreachable. A negative value will result
* in an IllegalArgumentException being thrown.
*
* @param timeout the time, in milliseconds, before the call aborts
*
* @return a {@code boolean} indicating if the address is reachable.
*
* @throws IOException if a network error occurs
* @throws IllegalArgumentException if {@code timeout} is negative.
* @since 1.5
*/
// 判断给定的网络地址是否可用
public boolean isReachable(int timeout) throws IOException {
return isReachable(null, 0, timeout);
}
/**
* Test whether that address is reachable. Best effort is made by the
* implementation to try to reach the host, but firewalls and server
* configuration may block requests resulting in a unreachable status
* while some specific ports may be accessible.
* A typical implementation will use ICMP ECHO REQUESTs if the
* privilege can be obtained, otherwise it will try to establish
* a TCP connection on port 7 (Echo) of the destination host.
* <p>
* The {@code network interface} and {@code ttl} parameters
* let the caller specify which network interface the test will go through
* and the maximum number of hops the packets should go through.
* A negative value for the {@code ttl} will result in an
* IllegalArgumentException being thrown.
* <p>
* The timeout value, in milliseconds, indicates the maximum amount of time
* the try should take. If the operation times out before getting an
* answer, the host is deemed unreachable. A negative value will result
* in an IllegalArgumentException being thrown.
*
* @param netif the NetworkInterface through which the test will be done, or null for any interface
* @param ttl the maximum numbers of hops to try or 0 for the default
* @param timeout the time, in milliseconds, before the call aborts
*
* @return a {@code boolean}indicating if the address is reachable.
*
* @throws IllegalArgumentException if either {@code timeout}
* or {@code ttl} are negative.
* @throws IOException if a network error occurs
* @since 1.5
*/
// 通过指定的网络接口判断给定的网络地址是否可用,ttl代表网络跳数
public boolean isReachable(NetworkInterface netif, int ttl, int timeout) throws IOException {
if(ttl<0) {
throw new IllegalArgumentException("ttl can't be negative");
}
if(timeout<0) {
throw new IllegalArgumentException("timeout can't be negative");
}
return impl.isReachable(this, timeout, netif, ttl);
}
/**
* Gets the host name for this IP address.
*
* <p>If this InetAddress was created with a host name,
* this host name will be remembered and returned;
* otherwise, a reverse name lookup will be performed
* and the result will be returned based on the system
* configured name lookup service. If a lookup of the name service
* is required, call
* {@link #getCanonicalHostName() getCanonicalHostName}.
*
* <p>If there is a security manager, its
* {@code checkConnect} method is first called
* with the hostname and {@code -1}
* as its arguments to see if the operation is allowed.
* If the operation is not allowed, it will return
* the textual representation of the IP address.
*
* @return the host name for this IP address, or if the operation
* is not allowed by the security check, the textual
* representation of the IP address.
*
* @see InetAddress#getCanonicalHostName
* @see SecurityManager#checkConnect
*/
// 获取当前网络地址的主机名
public String getHostName() {
return getHostName(true);
}
/**
* Gets the fully qualified domain name for this IP address.
* Best effort method, meaning we may not be able to return
* the FQDN depending on the underlying system configuration.
*
* <p>If there is a security manager, this method first
* calls its {@code checkConnect} method
* with the hostname and {@code -1}
* as its arguments to see if the calling code is allowed to know
* the hostname for this IP address, i.e., to connect to the host.
* If the operation is not allowed, it will return
* the textual representation of the IP address.
*
* @return the fully qualified domain name for this IP address,
* or if the operation is not allowed by the security check,
* the textual representation of the IP address.
*
* @see SecurityManager#checkConnect
* @since 1.4
*/
// 获取当前网络地址的主机名
public String getCanonicalHostName() {
String value = canonicalHostName;
if(value == null) {
canonicalHostName = value = InetAddress.getHostFromNameService(this, true);
}
return value;
}
/**
* Returns the raw IP address of this {@code InetAddress}
* object. The result is in network byte order: the highest order
* byte of the address is in {@code getAddress()[0]}.
*
* @return the raw IP address of this object.
*/
// 返回IP地址的字节形式
public byte[] getAddress() {
return null;
}
/**
* Returns the IP address string in textual presentation.
*
* @return the raw IP address in a string format.
*
* @since 1.0.2
*/
// 返回IP地址的文本形式
public String getHostAddress() {
return null;
}
/**
* Returns the hostname for this address.
* If the host is equal to null, then this address refers to any
* of the local machine's available network addresses.
* this is package private so SocketPermission can make calls into
* here without a security check.
*
* <p>If there is a security manager, this method first
* calls its {@code checkConnect} method
* with the hostname and {@code -1}
* as its arguments to see if the calling code is allowed to know
* the hostname for this IP address, i.e., to connect to the host.
* If the operation is not allowed, it will return
* the textual representation of the IP address.
*
* @param check make security check if true
*
* @return the host name for this IP address, or if the operation
* is not allowed by the security check, the textual
* representation of the IP address.
*