java核心技术卷 -- 网络编程

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();
        }
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章