说到网络编程,能想到的都有哪些呢?
网络编程和socket编程、ServerSocket、InetAddress、 URlConnection、RestTemplate、 HttpClient、套接字、shutdown、TCP、 UDP、OSI网络七层模型 ........
但是这些之间都有什么样的关系呢,究竟哪个对应底层,哪个对应实现呢?网络编程是否也有不同的实现方式呢,以及对应的应用场景分别是什么呢?
一、网络基础知识
1、网络分类
计算机网络种类按照不同的划分标准有多种。
规模大小和延伸范围:局域网(LAN)、城域网(MAN)、广域网(WAN)。Internet可是视为世界上最大的广域网
网络拓扑结构:总线型网络、环形网络、树形网络、星型网络
传输介质:双绞线网、同轴电缆网、光纤网、卫星网
2、网络设计
既然存在不同类型的网络,不同的网络之间要实现通讯要有统一的约定,这些约定就被称为通讯协议。
国际标准化组织提出的『开放系统互联参考模型』即著名的 OSI (Open System Interconnection ), 力求将网络简化,并以模块的方式设计网络。
OSI是一种理想的模型,并没有实际落地。 TCP/IP四层模型是对OSI的简化,这个模型和OSI七层模型有大致的对应关系:
3、IP地址和端口号
IP地址用于唯一的标识网络种的一个通讯实体,这个实体可以是一台主机,一个打印机,或者路由器的某个端口。IP地址是数字型的,是一个32位(32bit)整数,为了方便记忆,把它分成4个8位的二进制,每个8位的整数可以转换成一个0~255的十进制整数。也就有了常见的IP格式:202.9.128.88。IP地址分为A B C D E 五类。
IP协议为多点广播提供了一批特殊的IP地址,这些IP地址的范围是224.0.0.0至239.255.255.255。每一个广播地址都被看成一个组,当客户需要发送、接收广播信息时,加入到该组即可。
一个通讯实体可以运行多个进程,端口就是进程与外界交流的出入口。不同的应用程序对应唯一的端口号。端口号可以从0到65535,通常可以分为3类:
公认端口:从0~1023, 紧密绑定一些特殊的服务
注册端口:1024~49151,松散绑定一些服务,应用程序通常应该使用这个范围的端口
动态和/或私有端口:49152~65535,应用程序使用的动态端口,应用程序一般不会主动使用这些端口
二、Java对网络编程的支持
Java为网络支持提供了java.net包,该包下的URL和URLConnection等类提供了以编程方式访问Web服务的功能,而 URLDecoder 和 URLEncoder 提供了普通字符串 和 applicaiton/w-www-form-urlencoded MIME字符串转换的静态方法(区别于NIO中学习的CharsetDecoder和CharsetEncoder)。
2.1 使用InetAddress代表IP地址
InetAddress两个子类,分别代表IPv4和IPv6地址
示例:
|
2.2 URLDecoder 和 URLEncoder
URLDecoder 和 URLEncoder 提供了普通字符串 和 applicaiton/w-www-form-urlencoded MIME字符串 转换的静态方法
提问:什么是applicaiton/w-www-form-urlencoded MIME字符串呢?
URL地址中包含非西欧字符串时,系统会将这些非西欧字符串进行转换,转换的过程也就是编码的过程,这就需要使用到URLDecoder和URLEncoder类。
在转换中文字符时,每个中文字符占用两个字节,每个字节可以转换成两个十六进制的数据,所以每个中文字符转换成%XX%XX的形式。当然,采用不同的字符集,每个中文字符对应的字节数并不完全相同,所以使用URLDecoder和URLEncoder类进行转换时需要指定字符集。
转换方式:
示例:
|
2.3 URL、URLConnection、URLPermission
URL : 代表统一资源定位器(可以进行定位资源),是指向互联网资源的指针, 通常由协议名、主机、端口和资源组成,即满足如下格式:protocol://host:port/resourceName, 示例:http://www.crazyit.org/index.php
URI : 代表统一资源标识符(不能进行定位资源),相对URL,是不包含可以打开该资源的输入流的
URLConnection: 代表Java应用程序和URL表示的远程资源之间的通信链接。从这个连接中可以获取远程资源的输入流和相应信息
HttpURLConnection : 代表Java应用程序和URL表示的远程资源之间的HTTP链接
URLPermission : Java8中新增的类,用于管理HttpURLConnection的权限问题,如果在 HttpURLConnection安装了安全管理器,通过该对象打开连接时就需要先获得权限。
下面编程实现根据一个字符串的url创建连接,分别通过get 、post的方式发送请求,设置请求头信息,获取请求结果,打印响应内容:
主要步骤:
1)通过调用URL对象的 openConnection() 方法创建URLConnection对象
2)设置URLConnection的参数和普通请求属性,可以通过如下方法设置:
3) 如果时GET请求,使用connect()方法建立和远程资源嗯实际连接即可;如果是POST方式,则需要获取URLConnection实例对应的输出流来发送请求参数。
4)远程资源变为可用,程序可以访问远程资源的头字段 或 通过输入流读取远程资源的数据。可以通过如下方法访问响应的头字段和内容:
示例:
|
三、基于TCP协议的网络编程
IP协议 是网络层的协议,IP协议负责将消息从一个主机发送到另外一个主机,消息在传输的过程被分割成一个个数据包。无法解决数据分组在传输过程中可能出现的问题。
TCP协议是传输层的协议,是一种可靠的协议,是一种端对端的协议。TCP协议负责将分组的数据包按照适当的次序放好发送,TCP协议使用重发机制,保证数据传输过程的准确无误。
(但是有了TCP协议并不代表数据传输就一定没有问题,还可能出现粘包等问题)
Java对TCP协议的网络通讯提供了良好的封装,Java使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通讯。
3.1、使用ServerSocket创建TCP服务端
TCP通讯涉及到两端:服务端和客户端,而当两端的通信链路建立完成后,是无所谓服务端和客户端的,那么如何区分服务端呢?
服务端定义:用于监听客户端请求连接的一方被叫做服务端,负责监听客户端请求的方法是ServerSocket的accept()方法。
所以:Java中服务端用ServerSocket表示,客户端用Socket表示
建立TCP连接用到的类主要包括:ServerSocket、Socket;TCP链接中读取数据用到的类主要包括 InputStream、InputStreamReader、BufferedReader、PrintStream
3.1.1 ServerSocket主要方法:
1、构造方法:
ServerSocket(int port) :默认本地的IP地址
ServerSocket(int port, int backlog) : backlog表示连接队列的最大长度
ServerSocket(int port, int backlog, InetAddress bindAddr):指定需要绑定的IP地址
2、常用其他方法
Socket accept(): 如果接收到客户端Socket的连接请求,返回一个与客户端Socket对应的Socket;否则该方法处于等待状态,线程也会被阻塞(程序停在该方法处)
3.1.2 Socket的主要方法
1、构造方法
Socket(InetAddress/String host, int port):创建连接到指定远程主机和端口的Socket,没有指定本地地址和端口,默认是本机地址, 默认使用系统动态分配的端口
Socket(String host, int port, InetAddress localAddr, int localPort) :
1、主要方法
OutputStream getOutputStream() : 客户端使用,用于往socket中写数据
InputStream getInputStream() : 服务端使用,用于从socket中读数据
3.1.3 基于TCP协议的网络通讯简单示例
|
思考:上面客户端的示例中如果没有bufferedWriter.flush(),数据是不能发送到服务端的,那么Socket输出流如何表示输出的数据已结束?看下面3.1.4
3.1.4 Socket输出流如何表示输出的数据已结束?
重要问题:
Socket输出流如何表示输出的数据已结束?
1、关闭输出流会认为数据结束了(但是关闭输出流意味着对应的Socket也将关闭,这导致程序无法再从该Socket的输入流中读取数据,所以不可取)
2、