【0】README
0.1) 本文描述部分转自 core java volume 2 , 旨在理解 网络——连接到server 的基础知识 ;
0.2) for source code, please visit https://github.com/pacosonTang/core-java-volume/blob/master/coreJavaAdvanced/chapter3/SocketTest.java + https://github.com/pacosonTang/core-java-volume/blob/master/coreJavaAdvanced/chapter3/InetAddressTest.java ;
【1】连接到服务器相关
1)首先了解 telnet 这个工具,调试网络程序非常有帮助;
- 1.1)telnet 简介: Telnet是进行远程登录的标准协议和主要方式,它为用户提供了在本地计算机上完成远程主机工作的能力。可以用telnet命令来测试端口号是否正常打开还是关闭状态。
- 1.2)Telnet 客户端命常用命令:
- open : 使用 openhostname 可以建立到主机的 Telnet 连接。
- close : 使用命令 close 命令可以关闭现有的 Telnet 连接。
- display : 使用 display 命令可以查看 Telnet 客户端的当前设置。
- send : 使用 send 命令可以向 Telnet 服务器发送命令。支持以下命令:
- ao : 放弃输出命令。
- ayt : “Are you there”命令。
- esc : 发送当前的转义字符。
- ip : 中断进程命令。
- synch : 执行 Telnet 同步操作。
- brk : 发送信号。
上表所列命令以外的其他命令都将以字符串的形式发送至 Telnet 服务器。例如,sendabcd 将发送字符串 abcd 至 Telnet 服务器,这样,Telnet 会话窗口中将出现该字符串。 - quit : 使用 quit 命令可以退出 Telnet 客户端。
- 1.3)运行在远程计算机上的服务器软件不停等待那些希望与端口13 连接的网络请求。 一旦建立连接, 远程程序便发送回一行数据, 然后关闭该连接。
try (Socket s = new Socket("time-A.timefreq.bldrdoc.gov", 13))
{
InputStream inStream = s.getInputStream();
Scanner in = new Scanner(inStream);
while (in.hasNextLine())
对上述代码的分析(Analysis):
- A1)第一行打开一个套接字。它也是网络软件(如 telnet 提供本地计算机操作远程计算机的功能)中的一个抽象概念, 负责启动该程序内部和外部之间的通信;(干货——套接字的抽象概念的具体含义是网络软件,如telnet, 而telnet又是进行远程登录的标准协议和主要方式)
- A2)一旦套接字被打开: java.net.Socket 类中的getInputStream 方法就会返回一个 InputStream 对象,该对象可以像其他任何流对象一样使用;
【2】套接字超时
1)problem+solution
- 1.1)problem:从套接字读取信息时, 在有数据可供访问之前, 读操作将会被阻塞;
- 1.2)solution:对于不同的应用,应该确定合理的超时值,然后调用 setSoTimeout 方法设置这个超时值, 如:
Socket s = new Socket(...);
s.setSoTimeout(10000);
2)捕获SocketTimeoutException 异常:如果设置了超时, 并且之后的读操作和写操作在没有完成之前就超过了时间限制, 那么这些操作就会抛出 SocketTimeoutException 异常, 你可以捕获这个异常, 对超时做出反应;
3)另外还有一个超时问题需要解决(problem+solution):
- 3.1)下面这个构造器(problem): Socket(String host, int port) 会一直无限期地阻塞下去, 直到建立了到达主机的初始连接为止;
- 3.2)solution:可以通过先构建一个无连接的套接字,然后再使用一个超时来进行连接的方法解决这个问题: (干货——使用超时限制来解决Socket构造器可能无限阻塞下去的case)
Socket s = new Socket();
s.connect(new InetSocketAddress(host, port), timeout);
【3】因特网地址(主机名和因特网地址间的转换,使用InetAddress 类)
1)静态的getByName 方法可以返回代表某个主机的 InetAddress 对象, 如:
InetAddress address = InetAddress.getByName("www.baidu.com");
- 1.1)然后使用getAddress 方法来访问这些字节:
byte[] addressBytes = address.getAddress();
- 1.2)getAllByName方法:一些访问量较大的主机名通常会对应多个因特网地址, 以实现负责均衡。当客户端访问主机时, 会随机选择其中的一个。 可以通过调用 getAllByName 方法来获得所有主机: (干货——访问量较大的主机名通常会对应多个因特网地址,通过getAllByName方法获取所有的因特网地址)
String host = args[0];
InetAddress[] addresses = InetAddress.getAllByName(host);
- 1.3)可以使用静态的getLocalHost 方法来得到本地主机的地址:
InetAddress address = InetAddress.getLocalHost();