目录
一.基于TCP协议的Socket编程
一、Socket类和ServerSocket类
1. Socket类
2. ServerSocket类
二、 使用Socket编程实现登录功能
1. 实现单用户登录
2. 实现多客户端用户登录
3. InetAddress类
二.基于UDP协议的Socket编程
一、DatagramPacket类和DatagramSocket类
1. DatagramPacket类
2. DatagramSocket类
二、 使用Socket编程实现客户咨询
三.搭建JUnit测试框架
一、认识软件测试
1. 软件测试的意义
2. 软件测试的分类
二、 JUnit测试框架
1. JUnit测试框架概述
2. JUnit测试框架包介绍
三、 JUnit 3.x测试框架
1. JUnit 3.x测试框架概述
四、 JUnit 4.x测试框架
1. JUnit 4.x测试框架概述
五、 测试套件
四.Java网络编程章节总结
棒棒有言:生活不可能一帆风顺,总会有波折,总会有险阻。生活是个爱开玩笑的孩子,也许今天给你所有,明天又会让你一无所有,无需烦恼,该来的总会来,再黑的夜晚也会有黎明到来的那一刻。不管生活有多么曲折,只要拥有幸福的态度就能挺过漫漫长夜,就能迎来美好的明天。
本章简介:是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
作者: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程序员采用和证实了的优秀测试框架。