目录
一、DatagramPacket类和DatagramSocket类
👌 棒棒有言:生活不可能一帆风顺,总会有波折,总会有险阻。生活是个爱开玩笑的孩子,也许今天给你所有,明天又会让你一无所有,无需烦恼,该来的总会来,再黑的夜晚也会有黎明到来的那一刻。不管生活有多么曲折,只要拥有幸福的态度就能挺过漫漫长夜,就能迎来美好的明天。
👌 本章简介:是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
👍 作者:get棒棒给个关注呗
👍 重要:请给个关注哦!
(1)java.net包的两个类Socket和ServerSocket,分别用来实现双向安全连接的客户端和服务器
端,它们是基于TCP协议进行工作的,工作过程如同打电话的过程,只有双方都接通了,才能开始
通话。
(2)进行网络通信时,Socket需要借助数据流来完成数据的传递工作。
(3)一个应用程序要通过网络向另一个应用程序发送数据,只要简单地创建Socket,然后将数据
写入到与该Socket关联的输出流即可。对应的,接收方的应用程序创建Socket,从相关联的输入流
读取数据即可。
(4)注意:2个端点在基于TCP协议的Socket编程中,经常一个作为客户端,一个作为服务器
端,也就是遵循client-server模型。
Socket对象在客户端和服务器之间建立连接。可用Socket类的构造方法创建套接字,并将此套接字
连接至指定的主机和端口。
(1)构造方法
-->第一种构造方法以主机名和端口号作为参数来创建一个Socket对象。创建对象时可能抛出
UnknownHostException或IOException异常,必须捕获它们。
Socket s = new Socket(hostName,port);
-->第二种构造方法以InetAddress对象和端口号作为参数来创建一个Socket对象。构造方法可能抛
出IOException或UnknownHostException异常,必须捕获并处理它们。
Socket s = new Socket(address,port);
(2)常用方法
- package com.qn.kehu;
-
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.io.OutputStream;
- import java.io.Reader;
- import java.net.Socket;
- import java.net.UnknownHostException;
-
- public class Client {
- /*
- * 客户端通过输出流向服务器发送请求信息
- * 服务器端通过输入流接收客户端发送的请求信息
- * 服务器端通过输出流向客户端发送响应信息
- * 客户端通过输入流接收服务器端发送的响应信息
- */
-
- public static void main(String[] args) {
- Socket socket = null;
- OutputStream os =null;
- InputStream is =null;
- Reader reader =null;
- BufferedReader br = null;
-
- try {
- //创建Socket对象
- socket = new Socket("127.0.0.1", 10088);
- //获取输出流
- os = socket.getOutputStream();
-
- //向服务器发送请求信息
- String str = "我是客户端,我想问你一个问题";
- byte[] bytes =str.getBytes();
-
- os.write(bytes);
- //关闭套接字的输出流
- socket.shutdownOutput();
-
- //接收服务器端发送过来的响应消息
- is = socket.getInputStream();
- reader = new InputStreamReader(is);
- br = new BufferedReader(reader);
- String repety =br.readLine();
- System.out.println(repety);
-
- } catch (UnknownHostException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }finally{
- try {
- br.close();
- reader.close();
- is.close();
- os.close();
- socket.close();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- }
-
- }
ServerSocket对象等待客户端建立连接,连接建立以后进行通信。
(1)构造方法
-->第一种构造方法接受端口号作为参数创建ServerSocket对象,创建此对象时可能抛出
IOException异常,必须捕获和处理它。
ServerSocket ss = new ServerSocket(port);
-->第二种构造方法接受端口号和最大队列长度作为参数,队列长度表示系统在拒绝连接前可以拥
有的最大客户端连接数。
ServerSocket ss = new ServerSocket(port,maxqu);
(2)常用方法
-->Socket类中列出的方法也适用于ServerSocket类。
-->ServerSocket类具有accept()方法,此方法用于等待客户端发起通信,这样Socket对象就可用于
进一步的数据传输。
- package com.qn.kehu;
-
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.io.OutputStream;
- import java.io.Reader;
- import java.net.ServerSocket;
- import java.net.Socket;
-
- public class Service {
-
- public static void main(String[] args) {
-
- // 创建ServerSocket对象
- ServerSocket ss = null;
- Socket socket = null;
- InputStream is = null;
- Reader reader = null;
- BufferedReader br = null;
- OutputStream os = null;
- try {
- ss = new ServerSocket(10088);
- // 服务器怎么知道客户端发送了请求呢?服务器要一直侦听客户端的请求
- socket = ss.accept();
- // 侦听客户端的请求得到一个Socket对象,就可以通过该对象获得输入流,得到客户端的请求信息
- is = socket.getInputStream();
-
- reader = new InputStreamReader(is);
- br = new BufferedReader(reader);
- String str = br.readLine();
- System.out.println(str);
-
- // 服务器向客户端发送一个响应信息
- os = socket.getOutputStream();
- String info = "我是服务器端,我已经收到了你的请求信息";
- byte[] bytes = info.getBytes();
-
- os.write(bytes);
-
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- try {
- os.close();
- br.close();
- reader.close();
- is.close();
- socket.close();
- ss.close();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- }
- }
-
- }
-->Socket网络编程一般分成如下4个步骤进行:
(1)建立连接。
(2)打开Socket关联的输入/输出流。
(3)从数据流中写入信息和读取信息。
(4)关闭所有的数据流和Socket。
-->使用两个类模拟实现用户登录的功能,实现客户端向服务器端发送用户登录信息,服务器端显
示这些信息。
客户端实现步骤:
1)建立连接,连接指向服务器及端口。
2)打开Socket关联的输入/输出流。
3)向输出流中写入信息。
4)从输入流中读取响应信息。
5)关闭所有的数据流和Socket。
服务器端实现步骤:
1)建立连接,监听端口。
2)使用accept()方法等待客户端发起通信
3)打开Socket关联的输入/输出流。
4)从输入流中读取请求信息。
5)向输出流中写入信息。
6)关闭所有的数据流和Socket。
-->客户端和服务器端的交互,采用一问一答的模式,先启动服务器进入监听状态,等待客户端的
连接请求,连接成功以后,客户端先“发言”,服务器给予“回应”。
-->一问一答的模式在现实中显然不是人们想要的。一个服务器不可能只针对一个客户端服务,一
般是面向很多的客户端同时提供服务的,但是单线程实现必然是这样的结果。
-->解决这个问题的办法是采用多线程的方式,可以在服务器端创建一个专门负责监听的应用主服
务程序、一个专门负责响应的线程程序。这样可以利用多线程处理多个请求。
->客户端实现步骤:
1)建立连接,连接指向服务器及端口。
2)打开Socket关联的输入/输出流。
3)向输出流中写入信息。
4)从输入流中读取响应信息。
5)关闭所有的数据流和Socket。
-->服务器端实现步骤:
1)创建服务器线程类,run()方法中实现对一个请求的响应处理。
2)修改服务器端代码,让服务器端Socket一直处于监听状态。
3)服务器端每监听到一个请求,创建一个线程对象并启动。
-->java.net包中的InetAddress类用于封装IP地址和DNS。要创建InetAddress类的实例,可以使用
工厂方法,因为此类没有构造方法。
-->InetAddress类中的工厂方法
-->如果找不到主机,两种方法都将抛出UnknownHostNameException异常。
(1)基于TCP的网络通信是安全的,是双向的,如同打电话,需要先有服务端,建立双向连接
后,才开始数据通信。
(2)基于UDP的网络通信只需要指明对方地址,然后将数据送出去,并不会事先连接。这样的网
络通信是不安全的,所以只应用在如聊天系统、咨询系统等场合下。
(3)数据报是表示通信的一种报文类型,使用数据报进行通信时无须事先建立连接,它是基于
UDP协议进行的。
(4)Java中有两个可使用数据报实现通信的类,即DatagramPacket和DatagramSocket。
(5)DatagramPacket类起到容器的作用,DatagramSocket类用于发送或接收DatagramPacket。
(6)DatagramPacket类不提供发送或接收数据的方法,而DatagramSocket类提供send()方法和
receive()方法,用于通过套接字发送和接收数据报。
(1)构造方法
-->客户端要向外发送数据,必须首先创建一个DatagramPacket对象,再使用DatagramSocket对
象发送。
(2)常用方法
- package com.qn.kehu5;
-
- import java.io.IOException;
- import java.net.DatagramPacket;
- import java.net.DatagramSocket;
- import java.net.SocketAddress;
- import java.net.SocketException;
-
- /**
- * 示例06:升级示例05,发送方发送咨询问题,接收方回应咨询。
- *
- * @author 小厨Java
- *
- */
- public class Receive {
-
- public static void main(String[] args) {
- /*
- * 示例06:升级示例05,发送方发送咨询问题,接收方回应咨询。
- *
- * 接收方实现步骤如下:
- * (1)创建DatagramPacket对象,准备接收封装的数据。
- * (2)创建DatagramSocket对象,接收数据保存于DatagramPacket对象中。
- * (3)利用DatagramPacket对象处理数据。
- */
-
- DatagramSocket ds = null;
- DatagramPacket dp = null;
- DatagramPacket dpto = null;
- // 创建DatagramPacket对象,用来准备接收数据
- byte[] buf = new byte[1024];
- dp = new DatagramPacket(buf, 1024);
- try {
- // 创建DatagramSocket对象,接收数据
- ds = new DatagramSocket(8800);
- ds.receive(dp);
- // 显示接收到的信息
- String mess = new String(dp.getData(), 0, dp.getLength());
- System.out.println(dp.getAddress().getHostAddress() + "说:" + mess);
-
- String reply = "你好,我在,请咨询!";
- // 显示与本地对话框
- System.out.println("我 说:" + reply);
- // 创建DatagramPacket对象,封装数据
- SocketAddress sa = dp.getSocketAddress();
- dpto = new DatagramPacket(reply.getBytes(),
- reply.getBytes().length, sa);
- ds.send(dpto);
- } catch (SocketException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- ds.close();
- }
-
- }
-
- }
(1)构造方法
-->DatagramSocket类不维护连接状态,不产生输入/输出数据流,它的唯一作用就是接收和发送
DatagramPacket对象封装好的数据报。
(2)常用方法
- package com.qn.kehu5;
-
- import java.io.IOException;
- import java.net.DatagramPacket;
- import java.net.DatagramSocket;
- import java.net.InetAddress;
- import java.net.SocketException;
- import java.net.UnknownHostException;
-
- /**
- * 示例06:升级示例05,发送方发送咨询问题,接收方回应咨询。
- *
- * @author 小厨Java
- *
- */
- public class Send {
- /*
- * 示例06:升级示例05,发送方发送咨询问题,接收方回应咨询。
- *
- * 发送方实现步骤如下:
- * (1)获取本地主机的InetAddress对象。
- * (2)创建DatagramPacket对象,封装要发送的信息。
- * (3)利用DatagramSocket对象将DatagramPacket对象数据发送出去。
- */
-
- public static void main(String[] args) {
- DatagramSocket ds = null;
- InetAddress ia = null;
- String mess = "你好,我想咨询一个问题。";
- System.out.println("我说:" + mess);
- try {
- // 获取本地主机地址
- ia = InetAddress.getByName("localhost");
- // 创建DatagramPacket对象,封装数据
- DatagramPacket dp = new DatagramPacket(mess.getBytes(),
- mess.getBytes().length, ia, 8800);
- // 创建DatagramSocket对象,向服务器发送数据
- ds = new DatagramSocket();
- ds.send(dp);
-
- byte[] buf = new byte[1024];
- DatagramPacket dpre = new DatagramPacket(buf, buf.length);
- ds.receive(dpre);
- // 显示接收到的信息
- String reply = new String(dpre.getData(), 0, dpre.getLength());
- System.out.println(dpre.getAddress().getHostAddress() + "说:"
- + reply);
- } catch (UnknownHostException e) {
- e.printStackTrace();
- } catch (SocketException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- ds.close();
- }
-
- }
-
- }
-->利用UDP通信的两个端点是平等的,也就是说通信的两个程序关系是对等的,没有主次之分,
甚至它们的代码都可以完全是一样的,这一点要与基于TCP协议的Socket编程区分开来。
-->基于UDP协议的Socket网络编程一般按照以下4个步骤进行:
(1)利用DatagramPacket对象封装数据包。
(2)利用DatagramSocket对象发送数据包。
(3)利用DatagramSocket对象接收数据包。
(4)利用DatagramPacket对象处理数据包。
-->模拟客户咨询功能,实现发送方发送咨询问题,接收方接收并显示发送来的咨询问题。
发送方实现步骤:
1)获取本地主机的InetAddress对象。
2)创建DatagramPacket对象,封装要发送的信息。
3)利用DatagramSocket对象将DatagramPacket对象数据发送出去。
接收方实现步骤:
1)创建DatagramPacket对象,准备接收封装的数据。
2)创建DatagramSocket对象,接收数据保存于DatagramPacket对象中。
3)利用DatagramPacket对象处理数据。
-->在编写程序的过程中,代码完成以后必须进行测试和调试,也就是说程序员要对自己编写的代
码负责,既要保证代码的正确编译执行,又要保证与预期结果相符合,这就涉及到单元测试。
(1)测试是发现并指出软件(包括建模、需求分析、设计等阶段产生的各种文档产品)中存在的
缺陷的过程。
(2)测试指出软件中缺陷的确定位置,进行详细记录,并且同时给出与预期的结果偏差。
(3)一般软件测试采用人工或利用工具来完成。
(4)测试在软件开发周期中起着至关重要的作用:
-->测试可以找到软件中存在的缺陷,避免连锁负面反应的发生。
-->测试不仅为了找到缺陷,更能帮助管理者提升项目管理能力并预防缺陷的发生,改进管理措
施。
-->测试是评定软件质量的一个有效方法。
(1)根据测试的角度不同,软件测试有不同的分类标准。
(2)从是否关心软件内部结构和具体实现角度,可分为白盒测试和黑盒测试。
(3)从软件开发过程的阶段,可分为单元测试、集成测试和确认测试等。
(4)各种测试的偏重点不一样:
1)白盒测试
白盒测试也称为结构测试或逻辑驱动测试,它按照程序内部的结构来测试程序,这种方法是把程序
2)黑盒测试
黑盒测试也称为功能测试,它通过测试来检测每个功能是否能够正常使用。在测试中,把程序看成
一个不能打开的盒子,测试人员在完全不考虑程序的内部结构和内部特性的基础上,进行功能测
试。
3)单元测试
测试人员需要依据详细设计说明书和源程序清单,了解该模块的需求、条件和逻辑结构,对软件中
最小可测试单元进行检查和验证。所以,对于单元测试,很多由程序员自己来完成。
(1)单元测试在面向对象的开发中变得越来越重要,一个简单易用、功能强大的单元级测试框架
的产生为广大程序员带来了全新的测试体验。
(2)在Java编程环境中,JUnit测试框架(JUnit Framework)是一个已经被多数Java程序员采用
和证实了的优秀测试框架。
(3)JUnit是由Erich Game和Kent Beck共同编写的一个回归测试框架,主要特性有:
-->用于测试期望结果的断言
-->用于共享测试数据的测试工具。
-->用于方便地组织和运行测试的测试套件。
-->图文并茂的测试运行机器。
(4)JUnit是在极限编程和重构中被极力推荐使用的工具,因为它的优势突出,主要体现在以下几
个方面:
-->测试代码和产品代码分开。
-->易于集成到测试人员的构建过程中。
-->开放源代码,可以进行二次开发。
-->可以方便地对JUnit的功能进行扩展。
(1)JUnit由SourceForge发行,从其官方网站上可以查阅JUnit相关的帮助文档,同时可以下载
JUnit安装jar包,目前很多开发IDE环境都集成了该jar包,开发时只需要导入即可。
(2)JUnit测试框架包中包含了JUnit测试类所需的所有基类,实际上这个包也是整个JUnit的基础
框架。
(3)JUnit测试框架包中最基本的几个类和接口如下:
1)Assert静态类
-->Assert类包含了一组静态的测试方法,用来对比期望值和实际值逻辑,验证程序是否正确(这个
过程称之为断言),若测试失败则标识未通过测试。
-->Assert类提供了JUnit使用的一整套断言,是一系列断言方法的集合。
2)Test接口
-->Test接口使用了Composite设计模式,TestCase类和TestSuite类都实现了此接口。
-->所有实现了Test接口的类都要实现run()方法,该方法执行测试,并使用了TestResult实例接收测
试结果。
3)TestCase抽象类
-->TestCase抽象类代表了一个测试用例,负责测试时对客户类的初始化以及测试方法的调用。
-->启动TestCase的run()方法后即创建了一个TestResult实例。它是JUnit测试框架的核心部分。
4)TestSuite测试包类
-->TestSuite测试包类代表需要测试的一组测试用例,负责包装和运行所有的测试类。
-->对每一个类的测试,可能测试其多个方法,也可能是对多个方法的组合测试,TestSuite测试包
类就负责组装这些测试。
5)TestRunner运行包类
TestRunner运行包类是运行测试代码的运行器。
6)TestResult结果类
TestResult结果类集合了任意测试累加结果,测试时将TestResult实例传递给每个测试的run()方法
来保存测试结果。
(1)测试对于保证软件开发质量有着非常重要的作用,而单元测试是必不可少的测试环节。
(2)JUnit是一个非常强大的单元测试包,可以对一个或多个类的单个或多个方法进行测试,还可
以将不同的TestCase组合成TestSuite,是将测试任务自动化的工具。
(3)MyEclipse中集成了Junit,可以非常方便发地编写TestCase。
(4)Junit 3.x中会自动执行test开头的方法,这是依赖反射执行的。
2. 使用JUnit 3.x进行单元测试
(1)搭建Junit 3.x(.x代表版本)测试框架,必须了解以下几个方法的作用。
-->testXxx():JUnit 3.x自动调用并执行的方法,必须声明为public并且不能带参数,必须以test开
头,返回值为void。
-->setUP():初始化,准备测试环境。
-->tearDown():释放资源。
(2)上述3个方法的调用顺序为setUp()--->testXxx()--->tearDown()。
(3)使用JUnit 3.x进行单元测试一般按照以下3个步骤进行:
1)在Java工程中导入所需要的JUnit测试jar包,选中setUp()方法和tearDown()方法。
2)在Java工程中选中要测试的方法并完成测试类的方法编写。
3)执行程序,红色表示失败,绿色表示成功。
(1)JUnit 4.x对JUnit测试框架进行了颠覆性的改进。
(2)JUnit4.x主要利用JDK中的新特性Annotation的特点来简化测试用例的编写。
(3)JUnit 4.x搭建测试框架的步骤与JUnit3.x是一样的。
2. 使用JUnit 4.x进行单元测试
(1)JUnit 4.x中有很多的以@符号开头的各种元数据,就是JUnit 4.x中的注解Annotation。
(2)JUnit 4.x中的注解作用,简单来说就是起到指示测试程序测试步骤及标志的作用。
(3)JUnit 4.x中的常用注解如下所示:
(4)JUnit 3.x和JUnit 4.x进行单元测试的区别如下:
1)JUnit 3.x中的测试类必须继承TestCase,而JUnit 4.x则不是必需的。
2)JUnit 3.x的测试类必须重写TestCase的setUp()方法和tearDown()方法,分别执行初始化和释放
资源的操作。而相同的工作,在JUnit 4.x中是使用@Before和@After来标识的,并且方法名可以随
意定义。
3)JUnit 3.x中对某个类的某个方法进行测试时,测试类对应的测试方法是固定的,必须以test开
头,而JUnit 4.x中则不是这样鹅,只需要使用@Test标识即可。
4)使用JUnit 4.x进行测试用例的编写相对灵活,和编写一个普通类没有什么区别,只需要加上注
解标注即可,这种松耦合的设计理念相当优秀。
(1)JUnit测试框架提供了一种批量运行测试类的方法,称为测试套件。
(2)测试套件就是把几个测试类打包组成一套数组进行测试。这样,每次需要验证系统功能正确
性时,只执行一个或几个测试套件即可。
(3)测试套件的写法非常简单,只需要遵循以下规则即可:
-->创建一个空类作为测试套件的入口,保证这个空类使用public修饰,而且存在公开的不带有任何
参数的构造方法。
-->使用注解org.junit.runner.RunWith和org.junit.runner.Suite.SuiteClasses修饰这个空类。
-->将org.junit.runners.Suite作为参数传入注解RunWith,以提示JUnit使用套件运行器执行此类。
-->将需要放入此测试套件的测试类组成数组作为注解SuiteClasses的参数。
(4)测试套件中不仅可以包含基本的测试类,还可以包含其他测试套件,这样可以很方便地分层
管理不同模块的单元测试代码。
1、 网络中使用IP地址唯一标识一台计算机。IP地址由网络部分和主机部分共同组成,常用的IP地
址由A、B、C这3类。
2、 网络编程作为Java中的主要应用之一,可以通过使用java.net包来实现。
3、 TCP/IP套接字是最可靠的双向流协议。在等待客户端请求的服务器使用ServerSocket类,而要
连接至服务器的客户端则使用Socket类。
4、 基于UDP的网络编程中,DatagramPacket是起到数据容器作用的一个类,DatagramSocket是
用于发送或接收DatagramPacket的类。
5、 InetAddress是一个用于封装IP地址和DNS的类。
6、 简单易用、功能强大的单元级测试框架—JUnit测试框架(JUnit Framework)是一个已经被多
数Java程序员采用和证实了的优秀测试框架。