网络编程
1、网络编程概述
网络编程
在网络通信协议下,不同计算机上运行程序,可以进行数据传输
网络编程三要素
IP地址
概述
全称“互联网协议地址”,也称IP地址。是分配给上网设备的数字标签。设备在网络中的地址,是唯一的标识。常见的IP分类是ipv4、ipv6。
常用命令
ipconfig:查看本机IP地址
ping IP地址:检查网络是否连通
特殊的IP地址
127.0.0.1:是回送地址,也称本地回环地址,可以代表本机的IP地址,一般用来测试使用
端口
应用程序在设备中的唯一标识,用两个字节表示的整数值,它的取值范围是0~65535。一个端口只能被一个应用程序使用
协议
数据在网络中传输的规则,常见的规则有UDP协议和TCP协议
2、java中的IP操作
InetAddress的使用
为了方便我们对IP地址的获取和操作,java提供了一个类InetAddress供我们使用
InetAddress:此类表示Internet协议地址
方法名称 | 说明 |
---|---|
static InetAddress getByName(String host) | 在给定主机名的情况下获取InetAddress类对象 |
String getHostName() | 获取次IP的主机名 |
String getHostAddress () | 返回IP地址字符串(以文本表现形式) |
public class Test1 {
public static void main(String[] args) throws UnknownHostException {
InetAddress ia = InetAddress.getByName("主机IP或者主机名字");
System.out.println(ia.getHostName());
System.out.println(ia.getHostAddress());
}
}
3、TCP通信程序
1、TCP通信原理
TCP通信协议是一种可靠的通信协议,它在通信的两端各建立一个Socket对象,通信之前要保证连接已经建立,通过Socket产生IO流来进行网络通信。
2、TCP发送数据步骤
1.创建客户端的Socket对象:Socket类
Socket(String host, int port):与指定服务端连接
参数说明:
host表示服务器端的主机名,也可以是服务器端的IP地址,只不过类型是String类型的
port表示服务器端的端口
2.通过Socket对象获取网络中的输出流,写数据
OutputStream getOutputStream()
3.释放资源
void close()
3、TCP接受数据
1.创建服务器端的Socket对象:ServerSocket对象
ServerSocket(int port):构造方法,需要绑定一个端口号,port就是端口号
2.监听客户端连接,并接受连接,返回一个Socket对象
Socket accept():该方法回一直阻塞,直到建立成功
3.获取网络中的输入流,用来读取客户端发送过来的数据
InputStream getInputStream()
4.释放资源
void close()
示例:
服务器端:
public class TcpServer {
public static void main(String[] args) throws IOException {
//1、创建服务器端ServerSocket对象
System.out.println("服务器端启动~");
ServerSocket ss = new ServerSocket(6060);
//2、监听客户端连接
Socket check = ss.accept();
System.out.println(check.getInetAddress().getHostAddress() + "客户端连接成功~");
//6、基于Socket对象,创建网络输入流
InputStream is = check.getInputStream();
//7、接受客户端消息
int len;
byte[] bytes = new byte[1024];
while((len = is.read(bytes)) != -1){
System.out.println(new String(bytes, 0, len));
}
//8、释放资源
is.close();
check.close();
}
}
客户端:
public class TcpClient {
public static void main(String[] args) throws IOException {
//3、创建Socket对象
Socket client = new Socket("127.0.0.1", 6060);
//4、基于Socket对象,获取网络中的输出流
OutputStream os = client.getOutputStream();
//5、利用网络输出流,向服务器端发送消息
os.write("Hello World!".getBytes());
//9、释放资源
os.close();
client.close();
}
}
运行结果(先运行服务器端)
服务器端启动~
127.0.0.1客户端连接成功~
Hello World!
4、设计模式
1、单例设计模式
1.单例设计模式的作用
是一种常用的设计模式,通过单例模式可以保证项目中,应用该模式的这个类只有一个实例,这样做既可以节省内存,也可以共享数据。
2.实现步骤
- 将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象
- 在该类内部产生一个唯一的实例化对象,并将其封装为private static 类型的成员变量
- 定义一个静态方法返回这个唯一的对象
//饿汉式单例
public class Demo01 {
//创建本类唯一的对象
private static Demo01 demo = new Demo01();
//私有化构造方法
private Demo01(){
}
//创建静态方法返回本类唯一对象
public static Demo01 get(){
return demo;
}
}
//懒汉式单例
public class Demo02 {
//创建本类唯一的对象
private static Demo02 demo;//一开始不急着急实例化默认值为null
//私有化构造方法
private Demo02(){
}
//创建静态方法返回本类唯一对象,加上“synchronized”可以保证多线程下也只创建一个对象
public static synchronized Demo02 get(){
if(demo == null){
demo = new Demo02();
}
return demo;
}
}
2、多例设计模式
1、多列设计模式的作用
多利设计模式,是一种常用的设计模式之一。使用多例模式可以保证项目中,应用该模式的类有固定数量的实例,多例类要自我创建并管理自己的实例,还要向外界提供取本类实例化的方法。
2、实现步骤
- 创建一个类,将构造方法私有化
- 在类中定义该类被创建对象的总数
- 在类中定义存放该类实例的list集合
- 在类中提供静态代码块,在静态代码块中创建类的实例
- 提供获取类的实例化方法
public class Demo02 {
int id;
//在类中定义被创建对象的数量
private static final int MAX = 3;
//定义一个存放实例化的容器
private static List<Demo02> list = new ArrayList<>();
//在静态代码块中创建类的实例
static {
for (int i = 0; i < MAX; i++) {
list.add(new Demo02());
}
}
//创建获取实例的方法
public static Demo02 getDemo(){
//随机获取集合中的一个对象
return list.get(new Random().nextInt(MAX));
}
//私有化构造方法
private Demo02() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
5、Junit4单元测试
1、概述
单元测试就是编写测试代码,可以准确、快速的保证程序的正确性,Junit式java单元测试的框架。
JUnit4可以通过注解的方式来标记方法,让方法存在某种意义,常见的注解有:
@BeforeClass全局指挥执行一次,而且是第一个运行(标记的方法需要是一个静态无参无返回值方法)
@Before在测试方法运行之前运行(非静态无参无返回值方法)
@Test测试方法(此方法必须是非静态无参无返回值方法)主要用于测试的方法
@After在测试方法运行之后运行(非静态无参无返回值方法)
@AfterClass全局只会执行一次,而且是最后一个执行(标记的方法是一个静态无参无返回值的方法)
@Ignore忽略此方法
2、使用
1.限时测试
对于那些逻辑很复杂,循环嵌套比较深的程序,很有可能出现死循环,因此一定要采取一些预防措施。限时测试是一个很好的解决方案。我们给这些测试函数设定一个执行时间,超过了这个时间,他们就会被系统强行终止,并且系统还会向你汇报该函数结束的原因是因为超时,这样你就可以发现这些Bug了。要实现这一功能,只需要给@Test标注加一个参数即可
@Test(timeout = 1000)
// Timeout参数表明了你要设定的时间,单位为毫秒,因此1000就代表1秒。
public void squareRoot() {
while(true){
System.out.println("======");
}
}
2.断言
预先判断某个条件一定成立,如果条件不成立,则直接报错。
//第一个参数表示期望值
//第二个参数表示实际值
// 如果实际值和期望值相同,说明结果正确就测试通过,如果不相同,说明结果是错误的,就会报错
Assert.assertEquals( 期望值, 实际值);
Assert.assertEquals("异常原因", 期望值, 实际值);
//例如:
int result = 2 * 150;
Assert.assertEquals(300, result);