第二十一章

计算机应用实现了多台计算机间的互联,使得它们彼此之间能够进行数据交流。网络应用程序就是在已连接的不同计算机上运行的程序,这些程序借助于网络协议,相互之间可以交换数据。编写网络应用程序前,首先必须明确所要使用的网络协议。TCP/IP协议是网络应用程序的首选

21.1 网络程序设计基础

网络程序设计编写的是与其他计算机进行通信的程序。Java已经将网络程序所需要的元素封装成不同的类,用户只要创建这些类的对象,使用相应的方法,即使不具备有关的网络知识,也可以编写出高质量的网络通信程序。

21.1.1 局域网与互联网

为了实现两台计算机的通信,必须用一个网络线路连接两台计算机

服务器是指提供信息的计算机或程序,客户机是指请求信息的计算机或程序。网络用于连接服务器与客户机,实现两者间的相互通信。但是,有时在某个网络中很难将服务器与客户机区分开。我们通常所说的局域网(Local Area Network,LAN),就是一群通过一定形式连接起来的计算机,它可以由两台计算机组成,也可以由同一区域内的上千台计算机组成。将LAN延伸到更大的范围,这样的网络称为广域网(Wide Area Network,WAN)。我们熟悉的互联网(Internet),就是由无数的LAN和WAN组成的。

21.1.2 网络协议

网络协议规定了计算机之间连接的物理、机械(网线与网卡的连接规定)、电气(有效的电平范围)等特征,计算机之间的相互寻址规则,数据发送冲突的解决方式,长数据如何分段传送与接收等内容。就像不同的国家有不同的法律一样,目前网络协议也有多种。下面简单地介绍几个常用的网络协议。

1.IP协议

IP是Internet Protocol的简称,是一种网络协议。Internet网络采用的协议是TCP/IP协议,其全称是Transmission Control Protocol/Internet Protocol。Internet依靠TCP/IP协议,在全球范围内实现了不同硬件结构、不同操作系统、不同网络系统间的互联。在Internet网络上存在着数以亿计的主机,每台主机都用网络为其分配的Internet地址代表自己,这个地址就是IP地址。到目前为止,IP地址用4个字节,也就是32位的二进制数来表示,称为IPv4。为了便于使用,通常取用每个字节的十进制数,并且每个字节之间用圆点隔开来表示IP地址,如192.168.1.1。现在人们正在试验使用16个字节来表示IP地址,这就是IPv6,但IPv6还没有投入使用。

TCP/IP模式是一种层次结构,共分为4层,分别为应用层、传输层、互联网层和网络层。各层实现特定的功能,提供特定的服务和访问接口,并具有相对的独立性。

2.TCP与UDP协议

在TCP/IP协议栈中,有两个高级协议是网络应用程序编写者应该了解的,即传输控制协议(Transmission Control Protocol,TCP)与用户数据报协议(User Datagram Protocol,UDP)。

TCP协议是一种以固接连线为基础的协议,它提供两台计算机间可靠的数据传送。TCP可以保证数据从一端送至连接的另一端时,能够确实送达,而且抵达的数据的排列顺序和送出时的顺序相同。因此,TCP协议适合可靠性要求比较高的场合。就像拨打电话,必须先拨号给对方,等两端确定连接后,相互才能听到对方说话,也知道对方回应的是什么。

HTTP、FTP和Telnet等都需要使用可靠的通信频道。例如,HTTP从某个URL读取数据时,如果收到的数据顺序与发送时不相同,可能就会出现一个混乱的HTML文件或是一些无效的信息。

UDP是无连接通信协议,不保证数据的可靠传输,但能够向若干个目标发送数据,或接收来自若干个源的数据。UDP以独立发送数据包的方式进行。这种方式就像邮递员送信给收信人,可以寄出很多信给同一个人,且每一封信都是相对独立的,各封信送达的顺序并不重要,收信人接收信件的顺序也不能保证与寄出信件的顺序相同。

UDP协议适合于一些对数据准确性要求不高,但对传输速度和时效性要求非常高的网站,如网络聊天室、在线影片等。这是由于TCP协议在认证上存在额外耗费,可能使传输速度减慢,而UDP协议即使有一小部分数据包遗失或传送顺序有所不同,也不会严重危害该项通信。

注意

一些防火墙和路由器会设置成不允许UDP数据包传输,因此若遇到UDP连接方面的问题,应先确定所在网络是否允许UDP协议。

21.1.3 端口与套接字

一般而言,一台计算机只有单一的连到网络的物理连接(Physical Connection),所有的数据都通过此连接对内、对外送达特定的计算机,这就是端口。网络程序设计中的端口(port)并非真实的物理存在,而是一个假想的连接装置。端口被规定为一个在0~65535的整数。HTTP服务一般使用80端口,FTP服务使用21端口。假如一台计算机提供了HTTP、FTP等多种服务,那么客户机会通过不同的端口来确定连接到服务器的哪项服务上,如图21.3所示。

通常,0~1023的端口数用于一些知名的网络服务和应用,用户的普通网络应用程序应该使用1024以上的端口数,以避免端口号与另一个应用或系统服务所用端口冲突。

网络程序中的套接字(Socket)用于将应用程序与端口连接起来。套接字是一个假想的连接装置,就像插座一样可连接电器与电线,如图21.4所示。Java将套接字抽象化为类,程序设计者只需创建Socket类对象,即可使用套接字。

21.2 TCP程序

TCP网络程序设计是指利用Socket类编写通信程序。利用TCP协议进行通信的两个应用程序是有主次之分的,一个称为服务器程序,另一个称为客户机程序,两者的功能和编写方法大不一样。

①------服务器程序创建一个ServerSocket(服务器端套接字)对象,调用accept()方法等待客户机来连接。

②------客户端程序创建一个Socket对象,请求与服务器建立连接。

③------服务器接收客户机的连接请求,同时创建一个新的Socket对象与客户建立连接。随后服务器继续等待新的请求。

21.2.1 InetAddress类

java.net包中的InetAddress类是与IP地址相关的类,利用该类可以获取IP地址、主机地址等信息。

使用InetAddress类的getHostName()和getHostAddress()方法获得本地主机的本机名、本机IP地址。

注意

InetAddress类的方法会抛出UnknownHostException异常,所以必须进行异常处理。这个异常在主机不存在或网络连接错误时发生。

21.2.2 ServerSocket类

java.net包中的ServerSocket类用于表示服务器套接字,其主要功能是等待来自网络上的"请求",它可通过指定的端口来等待连接的套接字。服务器套接字一次可以与一个套接字连接。如果多台客户机同时提出连接请求,服务器套接字会将请求连接的客户机存入列队中,然后从中取出一个套接字,与服务器新建的套接字连接起来。若请求连接数大于最大容纳数,则多出的连接请求被拒绝。队列的默认大小是50。

ServerSocket类的构造方法通常会抛出IOException异常,具体有以下几种形式:

ServerSocket():创建非绑定服务器套接字。

ServerSocket(int port):创建绑定到特定端口的服务器套接字。

ServerSocket(int port, int backlog):利用指定的backlog创建服务器套接字,并将其绑定到指定的本地端口号上。

ServerSocket(int port, int backlog, InetAddress bindAddress):使用指定的端口、侦听backlog和要绑定到的本地IP地址创建服务器。这种情况适用于计算机上有多块网卡和多个IP地址的情况,用户可以明确规定ServerSocket在哪块网卡或哪个IP地址上等待客户的连接请求。

调用ServerSocket类的accept()方法,会返回一个和客户端Socket对象相连接的Socket对象。服务器端的Socket对象使用getOutputStream()方法获得的输出流,将指向客户端Socket对象使用getInputStream()方法获得的那个输入流;同样,服务器端的Socket对象使用getInputStream()方法获得的输入流,将指向客户端Socket对象使用getOutputStream()方法获得的那个输出流。也就是说,当服务器向输出流写入信息时,客户端通过相应的输入流就能读取,反之亦然。

注意

accept()方法会阻塞线程的继续执行,直到接收到客户的呼叫。如果没有客户呼叫服务器,那么System.out.println("连接中")语句将不会执行。语句如果没有客户请求,accept()方法没有发生阻塞,肯定是程序出现了问题。通常是使用了一个被其他程序占用的端口号,ServerSocket绑定没有成功。

yu = server.accept();

System.out.println("连接中");

21.2.3 TCP网络程序设计

明白了TCP程序工作的过程,就可以编写TCP服务器程序了。在网络编程中,如果只要求客户机向服务器发送消息,不要求服务器向客户机发送消息,称为单向通信。客户机套接字

和服务器套接字连接成功后,客户机通过输出流发送数据,服务器则通过输入流接收数据。下面是简单的单向通信的实例。

【例21.2】创建TCP/IP协议服务器

运行服务器端程序,将输出提示信息,等待客户呼叫。下面再来看一下客户端程序。

编写客户端程序,将用户在文本框中输入的信息发送至服务器端,并将文本框中输入的信息显示在客户端的文本域中。

说明

当一台机器上安装了多个网络应用程序时,很可能指定的端口号已被占用。还可能遇到以前运行良好的网络程序突然运行不了的情况,这种情况很可能也是由于端口被别的程序占用了。此时可以运行netstat-help来获得帮助,使用netstat-an命令来查看该程序所使用的端口

21.3 UDP程序

用户数据报协议(UDP)是网络信息传输的另一种形式。基于UDP的通信和基于TCP的通信不同,基于UDP的信息传递更快,但不提供可靠性保证。使用UDP传递数据时,用户无法知道数据能否正确地到达主机,也不能确定到达目的地的顺序是否和发送的顺序相同。虽然UDP是一种不可靠的协议,但如果需要较快地传输信息,并能容忍小的错误,可以考虑使用UDP。

基于UDP通信的基本模式如下:

将数据打包(称为数据包),然后将数据包发往目的地。

接收别人发来的数据包,然后查看数据包。

发送数据包的步骤如下:

(1)使用DatagramSocket()创建一个数据包套接字。

(2)使用DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)创建要发送的数据包。

(3)使用DatagramSocket类的send()方法发送数据包。

接收数据包的步骤如下:

(1)使用DatagramSocket(int port)创建数据包套接字,绑定到指定的端口。

(2)使用DatagramPacket(byte[] buf, int length)创建字节数组来接收数据包。

(3)使用DatagramPacket类的receive()方法接收UDP包。

注意

DatagramSocket类的receive()方法接收数据时,如果还没有可以接收的数据,在正常情况下receive()方法将阻塞,一直等到网络上有数据传来,receive()方法接收该数据并返回。如果网络上没有数据发送过来,receive()方法也没有阻塞,肯定是程序有问题,大多数情况下是因为使用了一个被其他程序占用的端口号。

21.3.1 DatagramPacket类

java.net包的DatagramPacket类用来表示数据包。DatagramPacket类的构造方法如下:

DatagramPacket(byte[] buf, int length)。

DatagramPacket(byte[] buf, int length, InetAddress address, int port)。

第一种构造方法在创建DatagramPacket对象时,指定了数据包的内存空间和大小。第二种构造方法不仅指定了数据包的内存空间和大小,还指定了数据包的目标地址和端口。在发

送数据时,必须指定接收方的Socket地址和端口号,因此使用第二种构造方法可创建发送数据的DatagramPacket对象。

21.3.2 DatagramSocket类

java.net包中的DatagramSocket类用于表示发送和接收数据包的套接字。该类的构造方法如下:

DatagramSocket()。

DatagramSocket(int port)。

DatagramSocket(int port, InetAddress addr)。

第一种构造方法创建DatagramSocket对象,构造数据报套接字,并将其绑定到本地主机任何可用的端口上。第二种构造方法创建DatagramSocket对象,创建数据报套接字,并将其绑定到本地主机的指定端口上。第三种构造方法创建DatagramSocket对象,创建数据报套接字,并将其绑定到指定的端口和指定的本地地址上。第三种构造函数适用于有多块网卡和多个IP地址的情况。

如果接收数据时必须指定一个端口号,不允许系统随机产生,此时可以使用第二种构造方法。比如有个朋友要你给他写信,那他的地址就必须确定,不确定是不行的。在发送数据时通常使用第一种构造方法,不指定端口号,而是系统为我们分配一个端口号,就像寄信不需要到指定的邮局去寄一样。

21.3.3 UDP网络程序设计

根据前面所讲的网络编程的基本知识以及UDP网络编程的特点,下面创建一个广播数据报程序。广播数据报是一项较新的技术,其原理类似于电台广播。广播电台需要在指定的波段和频率上广播信息,收听者也要将收音机调到指定的波段、频率,才可以收听广播内容。

【例21.3】创建UDP协议广播电台程序

接收广播程序。单击"开始接收"按钮,系统开始接收主机播出的信息;单击"停止接收"按钮,系统停止接收广播主机播出的信息。代码如下:

说明

发出广播和接收广播的主机地址必须位于同一个组内,地址范围为224.0.0.0~224.255.255.255,该地址并不代表某个特定主机的位置。加入同一个组的主机可以在某个端口上广播信息,也可以在某个端口上接收信息。

相关推荐
一个有女朋友的程序员12 分钟前
Spring Boot 整合 Smart-Doc:零注解生成 API 文档,告别 Swagger
java·spring boot·smart-doc
苹果醋332 分钟前
AI大模型竞赛升温:百度发布文心大模型4.5和X1
java·运维·spring boot·mysql·nginx
网安INF37 分钟前
CVE-2020-1938源码分析与漏洞复现(Tomcat 文件包含/读取)
java·网络·web安全·网络安全·tomcat·漏洞复现
nenchoumi31191 小时前
UE5 学习系列(九)光照系统介绍
java·学习·ue5
张乔241 小时前
spring boot项目整合mybatis实现多数据源的配置
java·spring boot·多数据源
GzlAndy1 小时前
Tomcat调优
java·tomcat
美好的事情能不能发生在我身上1 小时前
苍穹外卖Day11代码解析以及深入思考
java·spring boot·后端·spring·架构
辉辉健身中1 小时前
Maven入门(够用)
java·maven
星火飞码iFlyCode1 小时前
【无标题】
java·前端·人工智能·算法
不良手残2 小时前
Redisson + Lettuce 在 Spring Boot 中的最佳实践方案
java·spring boot·redis·后端