Java 基础——网络编程

一、网络编程简介

计算机网络是通过传输介质、通信设施和网络通信协议,把分散在不同地点的计算机设备互连起来,实现资源共享和数据传输的系统。网络编程就就是编写程序使联网的两个(或多个)设备(例如计算机)之间进行数据传输。Java 语言对网络编程提供了良好的支持,通过其提供的接口我们可以很方便地进行网络编程。

Java 的网络应用程序编程接口主要包括:

(1)通信套接字接口(Socket Interface):比较原始的通信方式,设备之间通信时,必须先对这些通信数据进行处理。
(2)远程方法调用(RMI):比较高层级的通信方式,只要通信双方约定好通信的接口,其他的通信细节就可以借助中间件来完成。

java.net 包中的 API 包含有类和接口,它们提供低层次的通信细节。你可以直接使用这些类和接口,来专注于解决问题,而不用关注通信细节

(1)处理 IP地址与域名、网络主机

● InetAddress:处理主机名和 IP 地址
● Inet4Address
● Inet6Adress

(2)关于 URL 通信协议

● URL:处理 URL 并下载 URL 的相关数据
● URLConnection

(3)关于 TCP 通信协议

● Socket:处理 TCP 通信协议

(4)关于 UDP 通信协议

● DatagramSocket:处理 UDP 通信协议

(5)服务器的使用问题

● SercerSocket:提供服务端使用

java.net 包中提供了两种常见的网络协议的支持:

● TCP : TCP是传输控制协议的缩写,它保障了两个应用程序之间的可靠通信。通常用于互联网协议,被称TCP/IP。 面向连接的,安全,效率低,开销大。
● UDP :UDP是用户数据报协议的缩写,一个无连接的协议,提供了应用程序之间要发送的数据的数据包。不安全,效率高,协议简单,开销小。

域名系统(DNS)

域名系统(DNS)是因特网的电话簿。人类通过域名在线访问信息,如 nytimes.com 或 espn.com。Web 浏览器通过 Internet 协议(IP)地址进行交互。DNS 将域名转换为 IP 地址,以便浏览器可以加载 Internet 资源。在解析域名时,可以首先采用静态域名解析的方法,如果静态域名解析不成功,再采用动态域名解析的方法,域名是互联网上的身份标识,是不可重复的唯一标识资源。
(1)加载网页涉及4个DNS服务器:

● DNS recursor - recursor 可以被认为是一个图书管理员,被要求在图书馆的某个地方找到一本特定的书。DNS recursor是一个服务器,旨在通过Web浏览器等应用程序从客户端计算机接收查询。通常,recursor负责发出其他请求以满足客户端的DNS查询。
● 根名称服务器 - 根服务器是将人类可读主机名转换(解析)为IP地址的第一步。它可以被认为是图书馆中指向不同书籍书籍的索引 - 通常它可以作为对其他更具体位置的参考。
● TLD名称服务器 - 顶级域名服务器(TLD)可以被视为库中特定的书架。此名称服务器是搜索特定IP地址的下一步,它托管主机名的最后一部分(在example.com中,TLD服务器是“com”)。
● 权限名称服务器 - 这个最终名称服务器可以被认为是书架上的字典,其中可以将特定名称翻译成其定义。权限名称服务器是名称服务器查询中的最后一站。如果权限名称服务器可以访问所请求的记录,它将把请求的主机名的IP地址返回给发出初始请求的 DNS Recursor(图书管理员)。
在这里插入图片描述

(2)DNS 工作流程

在这里插入图片描述
● 第一步:客户机提出域名解析请求,并将该请求发送给本地域名服务器。
● 第二步:当本地域名服务器收到请求后,就先查询本地缓存,如果有该纪录项,则本地域名服务器就直接把查询结果返回。
● 第三步:如果本地缓存中没有该纪录,则本地域名服务器就向根域名服务器发起迭代查询:如果根域名服务器缓存有该纪录项,则根域名服务器就直接把查询结果返回;否则根域名服务器解析出顶级域(.com)服务器的地址,再返回给本地域名服务器。
● 第四步:本地域名服务器去请求顶级域名服务器:如果顶级域名服务器缓存有该纪录项,则顶级域名服务器就直接把查询结果返回;否则顶级域解析出权限域(baidu.com)的地址,返回给本地域名服务器。本地服务器再向一步返回 域名服务器发送请求,然后接受请求 服务器查询自己 缓存,如果没 该纪录,则返回相关 下级 域名服务器 地址。
● 第五步:本地域名服务器向权限域名服务器www.baidu.com发起请求进行查询,权限域名服务器 www.baidu.com 告诉本地域名服务器所查询的主机的 IP 地址。
● 第六步:本地域名服务器把返回结果保存到缓存,以备下一次使用,同时还将结果返回给客户机。
在这里插入图片描述
为了提高DNS查询效率,并减轻服务器的负荷和减少因特网上的DNS查询报文数量,在域名服务器中广泛使用了高速缓存,用来存放最近查询过的域名以及从何处获得域名映射信息的记录。

1、网络编程的目的

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

2、网络编程中有两个主要的问题

① 如何准确地定位网络上一台或多台主机;定位主机上的特定的应用。

② 找到主机后如何可靠高效地进行数据传输。

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

① 通信双方地址:IP 和 端口号(通过 IP 地址准确定位主机,通过端口号准确定位主机上的应用)
② 一定的规则(即:网络通信协议,有两套参考模型)
● OSI 参考模型:模型过于理想化,未能在因特网上进行广泛推广。
● TCP/IP 参考模型(或TCP/IP协议):事实上的国际标准。

二、TCP 网络编程

1、Socket 介绍

Sokcet,即套接字,是一个对 TCP / IP 协议进行封装 的编程调用接口(API)。通过 Socket,我们可以基于 TCP/IP 协议进行开发。Socket 不是一种协议,而是一个编程调用接口(API),属于传输层(主要解决数据如何在网络中传输)。

套接字(Socket)是通信的基石,是支持 TCP/IP 协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议本地主机的IP地址本地进程的协议端口远地主机的IP地址远地进程的协议端口

应用层通过传输层进行数据通信时,TCP 会遇到同时为多个应用程序进程提供并发服务的问题。多个 TCP 连接或多个应用程序进程可能需要通过同一个 TCP 协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与 TCP/IP 协议交互提供了套接字(Socket)接口。应用层可以和传输层通过 Socket 接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。

(1)IP 地址:InetAddress(在 Java 中使用 InetAddress 类代表 IP)

● 唯一的标识 Internet 上的计算机(通信实体)。

● 本地回环地址(hostAddress):127.0.0.1 主机名(hostName):localhost。

● P地址分类方式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

● IP地址分类方式2:公网地址(万维网使用)和私有地址(局域网使用)。192.168. 开头的就是私有址址,范围即为192.168.0.0–192.168.255.255,专门为组织机 构内部使用。

(2)InetAddress 类

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

①域名(hostName):www.baidu.com

②IP 地址(hostAddress):14.215.177.38

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

● InetAddress 类对象含有一个 Internet 主机地址的域名和IP地址:www.baidu.com 和
14.215.177.38

(3)端口号

端口号就是标识正在计算机上运行的进程(程序),不同的进程有不同的端口号,被规定为一个 16 位的整数 0~65535。
在这里插入图片描述
端口分类:

① 公认端口:0~1023。被预先定义的服务通信占用(如:HTTP占用端口 80,FTP占用端口21,Telnet占用端口23)

② 注册端口:1024~49151。分配给用户进程或应用程序。(如:Tomcat占
用端口8080,MySQL占用端口3306,Oracle占用端口1521等)。

③ 动态/私有端口:49152~65535

(4)Socket分类:

1、 流套接字(stream socket):使用TCP提供可依赖的字节流服务

2、 数据报套接字(datagram socket):使用UDP提供“尽力而为”的数据报服务

2、基于 Socket 的 TCP 编程

套接字使用 TCP 提供了两台计算机之间的通信机制。客户端程序创建一个套接字,并尝试连接服务器的套接字。当连接建立时,服务器会创建一个 Socket 对象。客户端和服务器现在可以通过对 Socket 对象的写入和读取来进行通信。java.net.Socket 类代表一个套接字,并且 java.net.ServerSocket 类为服务器程序提供了一种来监听客户端,并与他们建立连接的机制。

1、Socket 通信的过程

Java 语言的基于套接字编程分为服务端编程和客户端编程,其通信模型如图所示:
在这里插入图片描述
(1)客户端Socket的工作过程包含以下四个基本的步骤:

创建 Socket:根据指定服务端的 IP 地址或端口号构造 Socket 类对象。若服务器端响应,则建立客户端到服务端的通信路线。若连接失败,则会出现异常。

打开连接到 Socket 的输入/出流: 使用 getInputStream() 方法获得输入流,使用 getOutputStream() 方法获得输出流,进行数据传输。

按照一定的协议对 Socket 进行读/写操作:通过输入流读取服务器放入线路的信息(但不能读取自己放入路线的信息),通过输出流将信息写入线程。

④ 关闭 Socket:断开客户端到服务器的连接,释放线路。
在这里插入图片描述

(2)服务器(服务端)程序的工作过程:

调用 ServerSocket(int port) :创建一个服务器端套接字,并绑定到指定端口上。用于监听客户端的请求。

调用 ServerSocket 类的 accept():监听连接请求,如果客户端请求连接,则接受连接,返回通信套接字对象。

调用该 Socket 类对象的 getOutputStream() 和 getInputStream ():获取输出
流和输入流,开始网络数据的发送和接收。

④ 关闭ServerSocket和Socket对象:客户端访问结束,关闭通信套接字。
在这里插入图片描述

综上,在两台计算机之间使用套接字建立TCP连接时的具体步骤为:

① 服务器实例化一个 ServerSocket 对象,绑定监听端口。
② 服务器调用 ServerSocket 类的 accept() 方法,该方法将一直等待,监听客户端请求,直到客户端连接到服务器上给定的端口。
③ 服务器正在等待时,一个客户端实例化一个 Socket 对象,指定服务器名称和端口号来请求连接。
④ Socket 类的构造函数试图将客户端连接到指定的服务器和端口号。如果通信被建立,则在客户端创建一个 Socket 对象能够与服务器进行通信。
⑤ 在服务器端,accept() 方法返回服务器上一个新的 socket 引用,该 socket 与客户端的 socket 连接建立后,通过使用 I/O 流读写进行通信,每一个 socket 都有一个输出流和输入流,客户端的输出流连接到服务器端的输入流,而客户端的输入流连接到服务器端的输出流。
在这里插入图片描述

2、Socket 编程的常用 API

(1)Socket 类

java.net.Socket类代表客户端和服务器都用来互相沟通的套接字。客户端要获取一个 Socket 对象实例化。而服务器获得一个 Socket 对象则通过 accept() 方法的返回值。
Socket类有五个构造方法:
在这里插入图片描述
当Socket构造方法返回,并没有简单的实例化了一个 Socket 对象,它实际上会尝试连接到指定的服务器和端口。客户端和服务器都有一个 Socket 对象,所以无论客户端还是服务器都能够调用这些方法。
在这里插入图片描述

(2)ServerSocket 类

服务器应用程序通过使用 java.net.ServerSocket 类以获取一个端口,并且侦听客户端请求。
ServerSocket 类共有四个构造方法:
在这里插入图片描述
如果 ServerSocket 构造方法没有抛出异常,就意味着你的应用程序已经成功绑定到指定的接口,并且侦听客户端请求。这里有一些 ServerSocket 类的常用方法:
在这里插入图片描述

(3)InetAddress 类

这个类表示互联网协议(IP)地址。下面列出了Socket编程时比较有用的方法:
在这里插入图片描述

3、网络编程 demo

服务端 server

public class Server {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        BufferedReader br = null;
        PrintWriter pw = null;
        System.out.println("服务端开启...");
        try{
        	// 创建 ServerSocket 对象,绑定监听端口 9000
            ServerSocket server = new ServerSocket(9000);
            // 监听客户端连接请求`,如果客户端请求连接,则接受连接,并返回通信套接字对象
            Socket socket = server.accept();
            // 获取 socket 的输入流
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            // 获取 socket 的输出流
            pw = new PrintWriter(socket.getOutputStream(),true);
            // 读取socket 的输入流数据,从而获得客户端发送的数据
            String s = br.readLine();
            System.out.print("接收到的是" + s);
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            try{
                br.close();
                pw.close();
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
}

客户端 client

public class Client {

    public static void main(String[] args) {

        BufferedReader br = null;
        OutputStream os = null;
        try{
            Socket socket = new Socket("localhost",9000);
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            // 获取 socket 的字节输出流
            os = socket.getOutputStream();
            // 将字符串转换为字节数组
            byte[] buffer = "hello".getBytes();
            // 将字节数组写入到客户端 socket 的输出流,从而发送到服务端
            os.write(buffer);
            System.out.println("发送的数据: " + new String(buffer));
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            try {
                br.close();
                pw.close();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

结果
在这里插入图片描述
在这里插入图片描述

三、UDP 网络编程

四、URL 类

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值