1.4因特网地址
是用一串数字表示的主机地址,一个因特网地址是由4个字节组成,如果需要在主机名和因特网地址之间进行转换,就需要使用InetAddress类
只要主机操作系统支持IPV6格式的因特网地址,java.net包也支持
静态的getByName方法可以返回代表某个主机的InteAddress地址。
可以通过调用getAllByName方法来获取所有主机
InetAdddress
package socket;
import java.net.InetAddress;
public class InetAddressTest {
public static void main(String[] args)throws Exception{
if(args.length > 0){
String host = args[0];
InetAddress[] addresses = InetAddress.getAllByName(host);
for(InetAddress a : addresses){
System.out.println(a);
}
}
else{
InetAddress localHostAddress = InetAddress.getLocalHost();
System.out.println(localHostAddress);
}
}
}
2.1服务器套接字
一旦启动了服务器程序,它便会等待某个客户端连接它的接口。
每一个服务器程序,比如一个HTTP Web服务器,都会不间断地执行这个循环
1.通过输入数据流从客户端接受一个命令(“get me this information”)
2.解码这个客户端命令
3.手机客户端所请求的命令
4.通过输出数据流发送信息给客户端
package socket;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class EchoServer {
public static void main(String[] args)throws Exception{
//建立套接字
try(ServerSocket s = new ServerSocket(8189)) {
//用于建立一个负责监控端口8189的服务器,等待连接,该方法阻塞知道当前对象建立连接为止
try(Socket incoming = s.accept()) {
InputStream inStream = incoming.getInputStream();
OutputStream outStream = incoming.getOutputStream();
try(Scanner in = new Scanner(inStream,"UTF-8")) {
PrintWriter out = new PrintWriter(new OutputStreamWriter(outStream, "UTF-8"),true);
out.println("Hello, Enter BYE to exit");
boolean done = false;
while (!done && in.hasNextLine())
{
String line = in.nextLine();
out.println("Echo"+ line);
if(line.trim().equals("BYE")) done = true;
}
}
}
}
}
}
2.2为多个客户端服务
每当建立一个新的套接字连接, 也就是当调用accept(),将会启动一个新的线程来处理服务器和该客户端之间的连接,而主程序将立即返回并等待下一个连接,
操作步骤
1.编译和运行服务器程序
2.打开数个telnet窗口 cmd -> telnet localhost 8189
3.在这些窗口之间切换,并键入命令,注意你可以同时通过这些窗口进行通信
4.当完成之后,切换到你启动服务器程序的窗口,并使用CTRL+C强行关闭
package socket;
import javax.sound.midi.Soundbank;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class ThreadedEchoServer {
public static void main(String[] args){
try(ServerSocket s = new ServerSocket(8189)) {
int i=1;
while(true){
Socket incoming = s.accept();
System.out.println("Spawning" + i);
Runnable r = new ThreadedEchoHandler(incoming);
Thread t = new Thread(r);
t.start();
i++;
}
}
catch (IOException e){
e.printStackTrace();
}
}
static class ThreadedEchoHandler implements Runnable{
private Socket incoming;
public ThreadedEchoHandler(Socket incomingSocket){
incoming = incomingSocket;
}
public void run(){
try(InputStream inStream = incoming.getInputStream();
OutputStream outStream = incoming.getOutputStream()) {
Scanner in = new Scanner(inStream,"UTF-8");
PrintWriter out = new PrintWriter(new OutputStreamWriter(outStream,"UTF-8"),true);
out.println("HELLO! ENTER BYE to exit");
boolean done = false;
while (!done && in.hasNextLine())
{
String line = in.nextLine();
out.println("Echo"+ line);
if(line.trim().equals("BYE")) done = true;
}
}
catch (IOException e){
e.printStackTrace();
}
}
}
}
2.3半关闭
套接字连接的一端可以终止其输出,同时仍旧可以接收来自另一端的数据
服务器端将读取输入信息,直至到达输入流的结尾,然后在发送响应
该协议只适用于一站式的服务,例如http服务,在这种服务中,客户端连接服务器,发送一个请求,捕获响应信息,然后断开连接。
Void shutdownOutput() 将输出流设置为”流结束”
Void shutdownInput() 输入流
Boolean isOutputShutdown() 如果输出已被关闭,则返回true
Boolean isInputShutdown() 输入被关闭,返回true
3.0可中断套接字
当连接到一个套接字时,当前线程将会被阻塞直到建立连接或者超时为止,同样,当通过套接字读取数据时,当前线程也会被阻塞直到操作成功或产生超时为止。
为了中断套接字操作,可以使用java.nio包提供的socketChannel类。
通道并没有与之相关联的流,实际上,所拥有的的read和write方法都是通过Buffer对象实现的。
如果不想处理缓冲区,可以使用Scanner类从SocketChannel中读取信息,因为Scanner有一个带ReadableByteChannel参数的构造器。
4.1URL和URI
URL 和URLConnection类封装了大量复杂的实现细节,例如,可以自一个字符串构建一个URL对象
URL url = new URL(urlString);
只想获取该资源的内容,可以使用URL类中的openStream方法。
URI是个纯粹的语法结构,包含用来指定web资源的字符串的各种组成部分,URL是URI的一个特例,包含了用于定位WEB 资源的足够信息。
在java类库中,URI类并不包括任何用于访问资源的方法,它的唯一作用是解析。
URI类的另一个作用是处理绝对标志符和相对标识符。
4.2使用URLConnection获取信息
当操作URLConnection对象时,应该小心的安排操作步骤
1.调用URL类中的openConnection方法获得URLConnection对象
URLConnection connection = url.openConnection()
2.使用以下方法设置任意的请求属性
setDoInput
setDoOutput //想获得输出流,需要调用
setIfModifyedSince //用于告诉连接你只对自某个特定时期以来被修改的时间
setUseCaches //用于命令浏览器首先检查它的缓存
setAllowUserInteraction //用于在访问有密码保护的资源时弹出对话框
setRequestProperty //设置对特定协议起作用的任何“名-值(name/value)对”
setConnectTimeout
setReadTimeout
3.调用connect方法连接远程资源
Connection.connect();
4.与服务器建立连接后,可以查询头信息
5.访问资源数据
package socket;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
public class URLconnectionTest {
public static void main(String[] args){
try {
String urlName;
if(args.length > 0) urlName = args[0];
else urlName = "http://horstmann.com";
URL url = new URL(urlName);
URLConnection connection = url.openConnection();
if(args.length>2){
String username = args[1];
String password = args[2];
String input = username + ":" + password;
Base64.Encoder encoder = Base64.getEncoder();
String encoding = encoder.encodeToString(input.getBytes(StandardCharsets.UTF_8));
connection.setRequestProperty("Authorization","Basic"+encoding);
}
connection.connect();
Map<String, List<String>> headers = connection.getHeaderFields();
for(Map.Entry<String,List<String>> entry : headers.entrySet()){
String key = entry.getKey();
for(String value:entry.getValue())
System.out.println(key+":"+ value);
}
System.out.println("----------");
System.out.println("getContentType: " + connection.getContentType());
System.out.println("getContentLength: " + connection.getContentLength());
System.out.println("getContentEncoding: " + connection.getContentEncoding());
System.out.println("getDate: " + connection.getDate());
System.out.println("getExpiration: " + connection.getExpiration());
System.out.println("getLastModifed: " + connection.getLastModified());
System.out.println("----------");
String encoding = connection.getContentEncoding();
if (encoding == null) encoding = "UTF-8";
try (Scanner in = new Scanner(connection.getInputStream(), encoding))
{
// print first ten lines of contents
for (int n = 1; in.hasNextLine() && n <= 10; n++)
System.out.println(in.nextLine());
if (in.hasNextLine()) System.out.println(". . .");
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}