InetAddress & Socket
/**
* @author yangxuyue
* @date 2018/2/25.
* At 9:45
*/
public class SocketTest {
/*
服务器一直监听希望与其端口相同的网络连接请求,
当监听到该请求后,它便唤醒正在监听网络连接请求的服务器进程,并为两者建立连接。
这种连接的保持,直到某一方的中止
*/
@Test
public void inetAddress() throws UnknownHostException {
/*
如果需要在主机名和因特网地址之间进行转换,需要InetAddress类
因为一些访问较大的主机名通常会对于多个因特网地址,以实现负载均衡,所以主机可以采用getAllByName(Srting host);获取
本地主机信息可以采用InetAddress.getLocalHost();获取
*/
InetAddress address = InetAddress.getByName("google.com");
byte[] addressByte = address.getAddress();
StringBuilder sb = new StringBuilder("[");
for (byte anAddressByte : addressByte) {
// 添加0x100(十进制256)是为了截取最后8位
String binaryString = Integer.toBinaryString((anAddressByte & 0xff) + 0x100).substring(1);
sb.append(Integer.parseInt(binaryString, 2)).append(",");
}
int length = sb.length();
sb.replace(length - 1, length, "]");
System.out.println(sb.toString());
System.out.println(Arrays.toString(addressByte));
}
@Test
public void socket() {
/*
解决超时:
1:
从套接字读取信息时,在有数据可供访问之前,读操作将会被阻塞,此时应该设置合理的超时时间
socket.setSoTimeout(int timeout);
2:
Socket socket = new Socket(String host, int port);
它将会一直阻塞下去,直到建立到达主机的初始连接为止
*/
try (Socket socket = new Socket()) {
// 解决超时问题2:超时10s
socket.connect(new InetSocketAddress("time-A.timefreq.bldrdoc.gov", 13), 10000);
// 解决超时问题1:超时10s
//socket.setSoTimeout(10000);
InputStream iStream = socket.getInputStream();
Scanner scanner = new Scanner(iStream);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
ServerSocket
/**
* 服务器
*/
public class Server {
// 启动;在命令行中敲:telnet localhost 6666 回车即可
public static void main(String[] args) throws IOException {
try (ServerSocket server = new ServerSocket(6666)) {
while (true) {
// 监听
Socket socket = server.accept();
// 防止一个连接的独占
Runnable task = new ServerTask(socket);
new Thread(task).run();
}
}
}
/**
* 为每个客户端建立一个线程去执行并不能满足高性能服务器的要求
* 为了使服务器有更高的吞吐量,可以使用java.nio包的一些特性
* 可中断套接字需要了解SocketChannel
*/
private static class ServerTask implements Runnable {
private Socket socket;
private ServerTask(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
InputStream iStream = socket.getInputStream();
OutputStream oStream = socket.getOutputStream();
try (Scanner scanner = new Scanner(iStream)) {
// 发送信息给客户端,自动flush
PrintWriter out = new PrintWriter(oStream, true);
out.println("Hello , Client ! Say 'bye' to exit!");
/*
半关闭:
如果关闭一个套接字,那么与服务器的连接将被中断,此时无法接收得到服务器的响应了
半关闭的方法可以解决这个问题:
可以通过关闭一个套接字的输出流来表示发送给服务器的请求数据已经结束,但是必须保持输入流处于打开状态
这种方式适合一站式的服务,如HTTP服务:客户端连接服务器,发送一个请求,捕获响应信息,最后断开连接
*/
//socket.shutdownOutput();
// 处理客户端发送过来的信息
boolean done = false;
while (!done && scanner.hasNextLine()) {
String line = scanner.nextLine();
System.out.println("Echo:" + line);
if (line.trim().equals("bye")) {
done = true;
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}