黑马程序员__Java网络编程

day23、24

1.网络通讯的要素:

  • 找到对方IP
  • 数据要发送到对方指定的应用程序上,为了标识这些应用程序,所以给这些网络应用程序都用数字进行标识。为了方便称呼,该数字叫做 端口! (这是逻辑接口)
  • 定义通讯规则,这个规则就是: 协议!  国际通用协议TCP/IP  还有很多其他协议

特殊IP:  127.0.0.1是回送地址,指默认情况下的本机地址

常见端口: web服务器80   Tomcat服务器8080  MySQL3306

2.传输协议有2种: TCP  UDP

OSI模型:     应用层 表示层 对话层    传输层  网络层  数据链路层 物理层

TCP/IP模型: 应用层        传输层  网际层  主机-网络层

javaweb开发处于: 应用层。

应用层的协议包括:  HTTP FTP  等

其中传输层定义了TCP、UDP协议,  网际层定义了IP协议,   java网络编程处理的是:网络层、传输层,不经过应用层

3.

  • IP地址:网络中设备的标识。      本机回环IP127.0.0.1   主机名:localhost
  • 端口号:用于标识进程的逻辑地址。   有效端口 0-65535, 0-1024为系统使用,即保留端口
  • 传输协议:通讯的规则。         常见协议 TCP  UDP 

4.InetAddress 类

该类没有构造函数,通过各种get方法获取对象。     由主机名+地址组成,如: www.baidu.com/111.13.100.92

        InetAddress ip = InetAddress.getLocalHost();    
        System.out.println(ip);
        System.out.println(ip.getHostAddress());
        System.out.println(ip.getHostName());
        static     InetAddress getLocalHost() //返回本地主机。         
        String        getHostAddress()// 返回对象的原始IP地址 
        String         getHostName()   // 返回对象的主机名 
        
        static  InetAddress     getByName(String host)  //返回指定主机的一个IP对象        
        static  InetAddress[]   getAllByName(String host) //返回指定主机的所有IP对象
        static  InetAddress     getByAddress(byte[] addr) 
 
        InetAddress ip = InetAddress.getLocalHost();    
        System.out.println(ip);  //输出tyh-PC/192.168.252.1
        System.out.println(ip.getHostAddress());  //输出192.168.252.1
        System.out.println(ip.getHostName());  //输出tyh-PC
        
        //给定主机名,会去联机查找其ip地址,返回主机名/地址
        //找不到时,抛出UnknownHostException异常
        InetAddress ip=InetAddress.getByName("www.qq.com");
        System.out.println(ip);//www.qq.com/111.30.132.101
        
        //给定ip地址得到ip对象,这种方式不会去查找name,仅仅创建一个ip对象
        //尽管这是百度ip,因为不联网查找,不知道主机名
        byte[] by = {111,13,100,92};    
        InetAddress ip = InetAddress.getByAddress(by);
        System.out.println(ip.getHostName());//111.12.100.92
        //一台主机可以有多个IP地址
        InetAddress[] is = InetAddress.getAllByName("www.baidu.com");
        for(InetAddress i:is)
            System.out.println(i);//www.baidu.com/111.13.100.91
                                  //www.baidu.com/111.13.100.92

5.TCP和UDP:

UDP协议特点:  User Datagram Protocol的简称, 中文名是用户数据报协议

  • 将数据及源和目的封装成数据包中,不需要建立连接
  • 每个数据报的大小限制在  64K
  • 因无连接,是不可靠协议
  • 不需要建立连接,速度快
  • 常用于: 视频传输 音频传输

TCP协议特点:

  • 建立连接,形成建立数据的通道
  • 在连接中进行大数据量传输
  • 通过三次握手完成连接,是可靠协议
  • 必须建立连接,效率会稍低

6. Socket   java网络编程指的就是Socket编程,Socket是为网络服务提供的一种机制

  • 通信的两端都有Socket,网络通信其实就是Socket的通信
  • 数据在两个Socket间通过IO传输

7. UDP传输

定义UDP发送端:

  • 建立Socket服务。
  • 提供数据,并将数据封装到数据包中。
  • 通过Socket服务中的发送功能,将数据包发出去。
  • 关闭资源。

定义UDP接收端:

  • 定义Socket服务,需要监听一个端口。其实就是给这个接收网络应用程序定义数字标识。
  • 定义数据包,用于存储接收的字节数据。  数据包对象的方法可以提取指定的数据
  • 通过Socket服务的receive方法将接收到的数据存入已经定义好的数据包中。
  • 通过数据包对象的特有功能,将这些数据取出
  • p关闭资源。
class UdpSend {

    public static void main(String[] args)throws Exception {
        //1.创建socket服务,通过DatagramSocket对象
        //可以不指定端口号,系统会随机分配一个
        //一台机器的一个端口在同一时间只能被一个程序占用,否则抛出Bind绑定异常
        DatagramSocket ds = new DatagramSocket(9000);
        
        //2.确定数据,封装成数据包
        byte[] buf = "udp 发送开始了。。。。".getBytes();
        byte[] byip = {112,37,77,68};//本机临时ip
        byte[] byip2 = {127,0,0,1};  //本机回环ip
        DatagramPacket dp = new DatagramPacket(buf, buf.length, 
                InetAddress.getByAddress(byip2), 10000);
        //当ip的后面是255时,代表广播地址,可以把数据广播到局域网
        
        //3.通过socket服务,将已有的数据包发送出去
        ds.send(dp);
        
        //4.关闭资源
        ds.close();
    }

}
  • class UdpRec { public static void main(String[] args)throws Exception { //1.创建socket,这里要指定需要监听的端口 DatagramSocket ds = new DatagramSocket(9999); //定义数据包,用于存储数据 byte[] buf = new byte[1024]; DatagramPacket dp = new DatagramPacket(buf, buf.length); //通过服务的receive方法将收到的数据存入数据包中。 //receive是一个阻塞式方法,没收到数据,就会一直wait ds.receive(dp); //通过数据包的方法取出包中的数据 String ip = dp.getAddress().getHostAddress(); String data = new String(dp.getData(),0,dp.getLength()); int port = dp.getPort(); System.out.println(ip+"::"+data+"::"+port); //关闭资源 ds.close(); } }

8.TCP传输:

不同于UDP,分为客户端、服务端,  Socket、 ServerSocket

客户端:

  • 创建Socket服务,指定要连接的主机和端口
  • 使用Socket的输出流发送数据
  • 关闭Socket对象

服务端:

  • 建立服务端的Socket服务,ServerSocket,并监听一个端口
  • 获取连接过来的客户端对象,通过accept方法
  • 使用客户端对象的流读取和发送数据
  • 关闭Socket对象,关闭服务端对象
class TcpClient {

    public static void main(String[] args) throws Exception{
        //创建客户端的Socket服务,指定目的主机和端口
        Socket s = new Socket("127.0.0.1",9999);
        
        //为了发送数据,应该获取Socket流中的输出流
        OutputStream out = s.getOutputStream();
        
        out.write("网络编程".getBytes());
        
        s.close();        
    }

}
class TcpServer {

    public static void main(String[] args)throws Exception {
        // 建立服务端Socket服务,并监听一个端口
        ServerSocket ss = new ServerSocket(9999);
        //通过accept方法来获取连接过来的客户端对象
        Socket s = ss.accept();
        System.out.println("连接成功");
        
        //获取客户端对象发送过来的数据,
        InputStream in = s.getInputStream();
         
        byte[] buf = new byte[1024];
        int len =  in.read(buf);
        System.out.println(new String(buf,0,len));
                
        s.close();
        ss.close();
    }

}

 ServerSocket类有一种特殊构造方法:

ServerSocket(int port, int backlog)
backlog - 队列的最大长度, 即能连接到服务器的最多客户端个数。

9.为了让多个客户端同时并发访问服务端,服务端最好的做法是将每个客户端封装到一个单独的线程中,这样,就可以同时处理多个客户端请求。

class PicClient {

    public static void main(String[] args)throws Exception {
        // TODO Auto-generated method stub
        Socket s = new Socket("127.0.0.1", 10000);
        
        BufferedInputStream bufr = new BufferedInputStream(new FileInputStream("abc.jpg"));
        OutputStream out = s.getOutputStream();
        int len=0;
        byte[] buf = new byte[1024];
        while((len=bufr.read(buf))!=-1)
            out.write(buf,0,len);
        s.shutdownOutput();
        
        
        InputStream in = s.getInputStream();
        byte[] bufIn = new byte[1024];
        int num = in.read(bufIn);
        System.out.println(new String(bufIn,0,num));
        
        bufr.close();
        s.close();
    }

}
class PicServer2 {

    public static void main(String[] args)throws Exception {
        ServerSocket ss= new ServerSocket(9980);
            
        while (true) {
            Socket s = ss.accept();
            new Thread(new PicThread(s)).start();
        }    
    }
}
class PicThread implements Runnable {

    private Socket s;
    public PicThread(Socket s){
        this.s = s;
    }
        
    public void run() {    
        int count = 0;
        try {
            String ip = s.getInetAddress().getHostAddress();
            System.out.println(ip+"。。连接成功");
            
            File file = new File(ip+"("+(count)+")"+".jpg");
            while(file.exists())
                file = new File(ip+"("+(count++)+")"+".jpg");
            
            InputStream in = s.getInputStream();            
            FileOutputStream fos = new FileOutputStream(file);
            byte[] buf = new byte[1024];
            int len = 0;
            while((len=in.read(buf))!=-1){
                fos.write(buf,0,len);    
            }
            
            OutputStream out = s.getOutputStream();
            out.write("上传成功".getBytes());
            
            fos.close();
            s.close();
            
        } catch (Exception e) {
            throw new RuntimeException("上传失败");
        }
    }

}

10.可以使用浏览器登录下面的服务端,也可以用telnet远程登录命令

class ServerDemo {

    public static void main(String[] args)throws Exception {
        //自定义服务端,使用浏览器登录
        ServerSocket ss = new ServerSocket(10000);    
        System.out.println("启动成功");
        Socket s = ss.accept();
        System.out.println("接收到"+s.getInetAddress().getHostAddress());
        PrintWriter pw = new PrintWriter(s.getOutputStream(),true);    
        pw.println("<font color='red'>客户端你好</font>");
        
        s.close();
        ss.close();
    }
}

11.可以自定义浏览器

浏览器软件的强大之处在于包含了很多解析引擎,比如Html解析引擎、CSS解析引擎、JavaScript解析引擎。

浏览器会首先向服务器发生一个头文件:

//chrome浏览器发送的
GET / HTTP/1.1
Host: 127.0.0.1:10000
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8


//IE浏览器发送的
GET / HTTP/1.1
Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, */*
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Win64; x64; Trident/4.0; .NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E; Media Center PC 6.0; Tablet PC 2.0)
UA-CPU: AMD64
Accept-Encoding: gzip, deflate
Host: 127.0.0.1:10000
Connection: Keep-Alive


-------------------------------

Http现在有2个版本,1.1是最新版本。

Keep-Alive表示IE与服务器之间会一直保持连接,但是如果一段时间没有响应,会超时,自动断开连接。 也可以设置为  closed

下面是自己实现的简单IE:

public class MyIE {

    public static void main(String[] args)throws Exception {
        // 
        Socket s = new Socket("127.0.0.1",8080);
        
        PrintWriter wr = new PrintWriter(s.getOutputStream(),true);
        wr.println("GET /tyh/demo.html HTTP/1.1");
        wr.println("Accept:*/*");
        wr.println("Accept-Language: zh-CN");
        wr.println("Host: 127.0.0.1:8080");
        wr.println("Connection: Keep-Alive");
        //这里必须跟2个空行! 这是请求头消息的结束格式
        wr.println();
        wr.println();
        
        BufferedReader bufr = new BufferedReader(new InputStreamReader(s.getInputStream()));
        String line = null;
        while((line=bufr.readLine())!=null)
            System.out.println(line);
        
        s.close();
    }

连接TomCat服务器之后,服务器也会发一个头消息:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Accept-Ranges: bytes
ETag: W/"7247-1422441251130"
Last-Modified: Wed, 28 Jan 2015 10:34:11 GMT
Content-Type: text/html
Content-Length: 7247
Date: Tue, 24 Feb 2015 09:27:16 GMT

200是响应状态码,代表ok。

12.URL类:

  • URL组成: 协议名://服务器名称(或IP地址):端口号/路径和文件名?查询
  • URL 可选择指定一个“端口”,它是用于建立到远程主机 TCP 连接的端口号。如果未指定该端口号,则使用协议默认的端口。例如,http 协议的默认端口为 80。

URL的常见构造方式:

URL(String spec)
URL(String protocol, String host, int port, String file)
URL(String protocol, String host, String file)

        URL url = new URL("http://cart.mi.com/cart/?你是谁?");
        System.out.println(url.getProtocol());//http
        System.out.println(url.getHost());//cart.mi.com
        System.out.println(url.getPort());//-1
        System.out.println(url.getPath());///cart/
        System.out.println(url.getFile());///cart/?你是谁?
        System.out.println(url.getQuery());//你是谁?
        

URLConnection类是一个抽象类

  • 它是所有表示应用程序与URL之间通信连接的类的父类(super class),该类的实例可以用来对由URL引用的资源进行读取和写入操作。
  • 它工作在应用层,将服务器发回的Http协议头信息隐藏
  • 它提供了方法,可以查看服务器发回的头信息
  • URLConnection类底层依赖Socket类实现网络连接,它比Socket类提供了更便利的网络连接抽象
        URL url2 = new URL("http://127.0.0.1:8080/tyh/demo.html");
        URLConnection openConnection = url2.openConnection();
        System.out.println(openConnection);
        InputStream in = openConnection.getInputStream();
        //打印  sun.net.www.protocol.http.HttpURLConnection:http://www.bjt.name/2013/09/emacs-configure/
        //也可以用in = url2.openStream()
        //该方法是下面方法的缩写:   openConnection().getInputStream()

    
        byte[] buf = new byte[1024];    
        int len = in.read(buf);
        System.out.println(new String(buf,0,len));        
        in.close();

13.当向浏览器输入一个地址时,浏览器先将地址解析一下,得到服务器名,一般输入的服务器名是域名(Domain Name),如:www.baidu.com

必须先将域名解析成ip地址,需要域名解析服务器(DNS)。

解析之前,会先搜索C:WindowsSystem32driversetc下的hosts文件,查看是否匹配,然后再去查询DNS服务器。


一个IP地址可以对应多个域名,一个域名也可以对应多个IP地址。

原文地址:https://www.cnblogs.com/tyh2014/p/4285216.html