(Java学习笔记)JavaSE 网络编程基础

网络编程基础

  • 1、网络编程概述
  • 2、网络通信要素概述
    • 2.1、如何实现网络中的主机互相通信
    • 2.2、网络通信协议
  • 3、通信要素一:IP和端口号
    • 3.1、IP地址
      • 3.11、作用:
      • 3.12、IP地址分类方式
      • 3.13、如何获取IP地址
    • 3.2、端口号
  • 4、通信要素二:网络协议
    • 4.1、基本概念
    • 4.2、TCP/IP协议簇
      • 4.21、TCP协议
      • 4.22、UDP协议
  • 5、TCP网络编程(基于Socket)
  • 6、UDP网络编程
  • 7、URL编程

1、网络编程概述

计算机网络:把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大、功能强的网络系统,从而使众多的计算机可以方便地互相传递信息、 共享硬件、软件、数据信息等资源。

网络编程目的:

直接或间接地通过网络协议与其它计算机实现数据交换,进行通讯。

网络编程中的两个主要问题:

  • 如何准确地定位网络上一台或多台主机;定位主机上的特定的应用
  • 找到主机后如何可靠高效地进行数据传输

2、网络通信要素概述

要素:IP和端口号 网络通信协议

2.1、如何实现网络中的主机互相通信

首先 知道通信双方地址

IP:区分不同的主机

端口号:区分相同主机的不用应用

其次 遵守一定的规则(网络通信协议)

网络通信协议参考模型

OSI参考模型、TCP/IP参考模型(TCP/IP协议)

2.2、网络通信协议

(Java学习笔记)JavaSE 网络编程基础_第1张图片

OSI参考模型:过于理想化 未能在因特网上进行广泛推广

TCP/IP协议:事实上的国际标准。

3、通信要素一:IP和端口号

3.1、IP地址

3.11、作用:

  1. 唯一的标识 Internet 上的计算机(通信实体)
  2. 本地回环地址(hostAddress):127.0.0.1 主机名(hostName):localhost

3.12、IP地址分类方式

  1. IPV4 和 IPV6

    • IPV4:4个字节组成,4个0-255。大概42亿,30亿都在北美,亚洲4亿。2011年初已 经用尽。以点分十进制表示,如192.168.0.1
    • IPV6:128位(16个字节),写成8个无符号整数,每个整数用四个十六进制位表示, 数之间用冒号(:)分开,如:3ffe:3201:1401:1280:c8ff:fe4d:db39:1984
  2. 公网地址(万维网使用)和私有地址(局域网使用)

    192.168. 开头的就是私有址址,范围即为192.168.0.0–192.168.255.255,专门为组织机 构内部使用 特点:不易记忆

3.13、如何获取IP地址

通过InetAddress类的实例化对象来获取

Internet上的主机有两种方式表示地址:

  1. 域名(hostName):www.baidu.com
  2. IP 地址(hostAddress):61.135.169.121

InetAddress类主要表示IP地址,两个子类:Inet4Address、Inet6Address。

域名容易记忆,当在连接网络时输入一个主机的域名后,域名服务器(DNS) 负责将域名转化成IP地址,这样才能和主机建立连接。 -------域名解析

package com.zck.tcpiptest;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * InetAddress的实例化
 * @author zck
 * @create 2020-04-16 19:18
 */
public class InetAddressTest {
     

    public static void main(String[] args) {
     
        InetAddress inet1 = null;
        InetAddress inet2 = null;
        InetAddress localHost = null;
        try {
     
            //实例化的方式:
            //获取对应的IP地址
            inet1 = InetAddress.getByName("192.164.119.100");
            //域名方式
            inet2 = InetAddress.getByName("www.baidu.com");
            //获取本机地址
            localHost = InetAddress.getLocalHost();

            //实例化对象的两个常用方法
            System.out.println(inet2.getHostName());
            System.out.println(inet2.getHostAddress());

        } catch (UnknownHostException e) {
     
            e.printStackTrace();
        }
        System.out.println(inet1);
        System.out.println(inet2);
        System.out.println(localHost);
    }
}

3.2、端口号

端口号标识正在计算机上运行的进程(程序)

不同的进程有不同的端口号

范围:被规定为一个 16 位的整数 0~65535。

端口号分类

  • 公认端口:0~1023。被预先定义的服务通信占用(如:HTTP占用端口 80,FTP占用端口21,Telnet占用端口23)
  • 注册端口:1024~49151。分配给用户进程或应用程序。(如:Tomcat占 用端口8080,MySQL占用端口3306,Oracle占用端口1521等)。
  • 动态/私有端口:49152~65535。

端口号与IP地址的组合得出一个网络套接字:Socket。

4、通信要素二:网络协议

4.1、基本概念

网络通信协议:

计算机网络中实现通信必须有一些约定,即通信协议,对速率、传输代码、代码结构、传输控制步骤、出错控制等制定标准。

通信协议分层:

计算机网络通信涉及内容很多,比如指定源地址和目标地址,加密解密,压缩 解压缩,差错控制,流量控制,路由控制,通过分层来实现复杂的网络协议

即:在制定协议时,把复杂成份分解成一些简单的成份,再将它们复合起来。最常用的复合方式是层次方式。**同层间可以通信、上一层可以调用下一层,而与 再下一层不发生关系。**各层互不影响,利于系统的开发和扩展。

4.2、TCP/IP协议簇

TCP/IP 以其两个主要协议:传输控制协议(TCP)和网络互联协议(IP)而得 名,实际上是一组协议,包括多个具有不同功能且互为关联的协议

传输层协议中有两个非常重要的协议:

  1. 传输控制协议TCP(Transmission Control Protocol)
  2. 用户数据报协议UDP(User Datagram Protocol)

IP(Internet Protocol)协议是网络层的主要协议,支持网间互连的数据通信。

TCP/IP协议模型从更实用的角度出发,形成了高效的四层体系结构,即物理链路层、IP层、传输层和应用层。

4.21、TCP协议

TCP生活举例:打电话

  • 使用TCP协议前,须先建立TCP连接,形成传输数据通道
  • 传输前,采用“三次握手”方式,点对点通信是可靠的
  • TCP协议进行通信的两个应用进程:客户端、服务端
  • 在连接中可进行大数据量的传输
  • 传输完毕,需释放已建立的连接,效率低
  • 释放连接的方式为“四次挥手”(客户端与服务端都可以主动断开连接,但通常是由客户端断开连接)

4.22、UDP协议

UDP生活举例:发短信

  • 将数据、源、目的封装成数据包,不需要建立连接
  • 每个数据报的大小限制在64K内
  • 发送不管对方是否准备好,接收方收到也不确认,故是***不可靠的***
  • 可以广播发送
  • 发送数据结束时无需释放资源,开销小,速度快

5、TCP网络编程(基于Socket)

客户端创建Socket对象,服务器建立 ServerSocket 对象

先启动服务端,再启动客户端

package com.zck.tcpiptest;

import org.junit.Test;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 实现TCP的网络编程
 * 客户端发送一条信息给服务端
 *
 * @author zck
 * @create 2020-04-17 14:53
 */
public class TCPTest1 {
     
    //客户端
    @Test
    public void client() {
     
        Socket socket = null;
        OutputStream outputStream = null;
        try {
     
            //1.创建Scoket对象,指明服务端的IP和端口号
            //本机地址:127.0.0.1或InetAddress.getLocalHost().getHostAddress()来获取
            InetAddress inet = InetAddress.getByName(InetAddress.getLocalHost().getHostAddress());
            socket = new Socket(inet, 8989);
            //2.获取输出流,用于输出数据
            outputStream = socket.getOutputStream();
            //3.写出操作
            outputStream.write("你好,我是客户端".getBytes());
        } catch (IOException e) {
     
            e.printStackTrace();
        } finally {
     
            //4.资源关闭
            if (outputStream != null) {
     
                try {
     
                    outputStream.close();
                } catch (IOException e) {
     
                    e.printStackTrace();
                }
            }

            if (socket != null) {
     
                try {
     
                    socket.close();
                } catch (IOException e) {
     
                    e.printStackTrace();
                }
            }
        }

    }

    //服务端
    @Test
    public void server() {
     
        ServerSocket serverSocket = null;
        Socket accept = null;
        InputStream inputStream = null;
        ByteArrayOutputStream baos = null;
        try {
     
            //1.创建服务器端的SeverSocket对象,指明自己的端口号
            serverSocket = new ServerSocket(8989);
            //2.调用accept(),表示接受来自服务端的数据
            accept = serverSocket.accept();
            //3.获取输入流
            inputStream = accept.getInputStream();
            //不建议这样写:可能会出现乱码   字节强转为String时,汉字(3个字节)解码可能出现错误
//        byte[] bytes = new byte[20];
//        int lenth;
//        while ((lenth = inputStream.read(bytes)) != -1){
     
//            String s = new String(bytes, 0, lenth);
//            System.out.print(s);
//        }
            //4.读取输入流的数据
            baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[5];
            int len;
            while ((len = inputStream.read(buffer)) != -1) {
     
                baos.write(buffer, 0, len);
            }
            System.out.println(baos.toString());
            System.out.println("收到了来自于" + accept.getInetAddress().getHostAddress() + "的数据");
        } catch (IOException e) {
     
            e.printStackTrace();
        } finally {
     
            //5.资源关闭
            if (baos != null) {
     
                try {
     
                    baos.close();
                } catch (IOException e) {
     
                    e.printStackTrace();
                }
            }
            if (accept != null) {
     
                try {
     
                    accept.close();
                } catch (IOException e) {
     
                    e.printStackTrace();
                }
            }
            if (inputStream != null) {
     
                try {
     
                    inputStream.close();
                } catch (IOException e) {
     
                    e.printStackTrace();
                }
            }
            if (serverSocket != null) {
     
                try {
     
                    serverSocket.close();
                } catch (IOException e) {
     
                    e.printStackTrace();
                }

            }
        }
    }
}

6、UDP网络编程

UDP数据报通过数据报套接字 DatagramSocket 发送和接收,系统不保证 UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达

操作步骤

  1. DatagramSocket与DatagramPacket
  2. 建立发送端,接收端
  3. 建立数据包
  4. 调用Socket的发送、接收方法
  5. 关闭Socket

注:发送端与接收端是两个独立的运行程序

package com.zck.tcpiptest;

import org.junit.Test;

import java.io.IOException;
import java.net.*;

/**
 * 实现UDP的网络编程(了解)
 * 注:未使用try-catch 异常处理
 * @author zck
 * @create 2020-04-17 16:09
 */
public class UDPTest {
     
    //发送端
    @Test
    public void send() throws IOException {
     
        DatagramSocket datagramSocket = new DatagramSocket();
        String str = new String("我是UDP方式发送的数据!");
        byte[] strBytes = str.getBytes();
        InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
        DatagramPacket datagramPacket = new DatagramPacket(strBytes,0,strBytes.length,inetAddress,8080);
        datagramSocket.send(datagramPacket);

        datagramSocket.close();
    }

    //接收端
    @Test
    public void receive() throws IOException {
     
        DatagramSocket datagramSocket = new DatagramSocket(8080);

        byte[] buffer = new byte[200];
        DatagramPacket datagramPacket = new DatagramPacket(buffer,0,buffer.length);
        datagramSocket.receive(datagramPacket);
        System.out.println(new String(datagramPacket.getData(),0,datagramPacket.getLength()));

        datagramSocket.close();
    }

}

7、URL编程

URL(Uniform Resource Locator):统一资源定位符,它表示 Internet 上某一 资源的地址

通过 URL 我们可以访问 Internet 上的各种网络资源,比如最常见的 www,ftp 站点。浏览器通过解析给定的 URL 可以在网络上查找相应的文件或其他资源。

URL的基本结构由5部分组成:

<传输协议>://<主机名>:<端口号>/<文件名>#片段名?参数列表

 public static void main(String[] args) throws MalformedURLException {
     
        URL url = new URL("https://top.jd.com/?cateId=653&itemId=100008348542");
//public String getProtocol( ) 获取该URL的协议名
        System.out.println(url.getProtocol());
//public String getHost( ) 获取该URL的主机名
        System.out.println(url.getHost());
//public String getPort( ) 获取该URL的端口号
        System.out.println(url.getPort());
//public String getPath( ) 获取该URL的文件路径
        System.out.println(url.getPort());
//public String getFile( ) 获取该URL的文件名
        System.out.println(url.getFile());
//public String getQuery( ) 获取该URL的查询名
        System.out.println(url.getQuery());
    }

控制台结果:

https
top.jd.com
-1
-1
/?cateId=653&itemId=100008348542
cateId=653&itemId=100008348542

注:本文章是根据哔哩哔哩公开课 Java -Java 学习- Java 基础到高级-宋红康-零基础自学Java-尚硅谷 整理所得
大爱康师傅!!!

你可能感兴趣的:(JavaSE笔记,java,socket,网络协议)