网络基础
网络基础知识
- 网络:
- 把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模宏大、功能强大的网络系统,从而使众多的计算机可以方便地互相传递信息,共享硬件、软件、数据信息等资源。
- Internet的形成和发展
- 第一阶段(1969~1983):1969年,美国ARPANET诞生,用于将几个军事及研究用的主机联系起来。1983年,TCP/IP应用到ARPANET中,使得internet得以迅速发展。以ARPANET 为中心,组成新的互联网(internet),称为Internet。
- 第二阶段(1983~1994):用于教育和科研领域的NSFNET(National Science Foundation Net)形成
- 第三阶段(1994~Now):Internet的商业化运作。
网络用用的基本结构
- clent和Server
网络三要素
- IP地址:用于唯一识别连接奥Internet上的计算机
- 地址表示方式
- IPv4:点分10进制表示方式,四个整数用点分开,每个十进制数字代表一个8bits整数,如192.168.123.1
- IPv6:点分16进制表示方式,八个整数用点分开,每个十六进制数字代表一个16bits整数,如CDCD:910A:2222:5498:8475:1111:3900:2020
- 域名
- 本地IP
- 127.0.0.1 等同于 localhost
- 端口号
- 在使用端口时,遵循如下的规则
- 低于255:用于公认端口
- 255~1023:分配给公司用于商业的应用
- 高于1023:没有限制
所以,如果建立自己的应用,都使用高于1023的端口 - 协议
- 在使用端口时,遵循如下的规则
网络分层
OSI的分层思想
- OSI:开放系统互连(Open System Interconncetion),采用分层的结构化技术
- 分层的理由:
- 将网络简化
- 模块化的设计网络
- OSI参考模型,(OSI/RM,Open System Interconnection/Reference Model)共分为7层,最高层为用户层,最底层为物理层。
网络通讯协议
- 在网络中的每台计算机都是一个节点,对于这些节点之间的交流,必须遵循有关节点之间都应该遵守的规则,这些所谓的规则就是”协议”;
- 计算机网络中要实现通讯必须有一些约定,就是通讯协议,对速率、传输代码、代码结构、传输控制步骤,出错控制等指定标准
TCP协议
- TCP:传输控制协议,TCP协议是一种可靠的端对端协议,当一台计算机需要和另外一台计算机通讯的时候,TCP协议会让他们之间建立一个连接,然后发送和接收数据,最后终止连接;
- TCP协议利用重发技术,向引用程序提供可靠的通讯连接,TCP会重发一切没有收到的数据,在接收数据时要进行确认并对数据进行排序,保证数据的完整性和正确性。
Java中的”ping”
- 在命令行中,可以通过”ping [host]”的方法得到指定主机的IP地址
- 通过java.net中的InetAddress类,可以得到指定主机的IP地址
获取IP地址示例
import java.net.*;
public class InetAddressTest {
public static void main(String[] args) {
try {
InetAddress ia = InetAddress.getLocalHost();
String host = ia.getHostAddress();
String hostname = ia.getHostName();
System.out.println(ia + " " + hostname);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
Socket
- 套接字(Socket):计算机之间相互通讯的一种方式,表示一个系统的IP地址和端口号的结合,Socket大致位于OSI的会话层,作为会话层的一部分,Socekt隐藏了数据流传输中的具体的过程,两个通讯的Socket会建立一个连接通道,然后在这个通道上通讯。
- TCP/IP连接的一个端点
- 用来处理两个流对象
- 创建TCP Socket需要的四个信息
- 本地系统的IP
- 本地应用程序使用的TCP端口号
- 远程系统的IP
- 远程用用程序相应的TCP端口号
TCP编程
- TCP编程
- java.net.Socket
- java.net.ServerSocket
- 服务器端:
- 创建ServerSocket对象(并绑定端口)
- 调用accept方法,等待来自客户端的连接
- 调用getXXXStream方法,进行I/O
- 关闭Socket
- 客户端:
- 创建Socket对象,并连接服务器
- 调用getXXXStream方法,进行I/O
- 关闭Socekt
TCP编程示例
第一步:服务器端创建ServerSocekt,等待客户端请求
//创建ServerSocekt对象并绑定端口
ServerSocket serverSocket = new ServerSocket(9000);
//调用accept()阻塞方法,阻塞到此处,等待客户端请求,当客户端请求时,返回socket对象
Socket socket = serverSocket.accpet();
//调用socket方法,创建字节输入流和输出流
InputStrem input = socket.getInputStream();
OutputStream output = socket.getOutputStream();
第二步:客户端创建一个Socket对象,发起请求,建立与服务器端的连接
//创建Socket对象,并连接服务器
/**
*此时服务器端的accept()方法产生返回值,
*返回一个Socket对象,
*客户端金额服务器端都有了输入流和输出流了,
*两端通过这两个流发送数据和接收数据
**/
Socket socket = new Socket("127.0.0.1",9000);
//调用socket方法,创建字节输入流和输出流
InputStream input = socket.getInputStream();
OutputStream output = socket.getOutputStream();
Socket通讯模型
反射的基本概念
- 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力, 并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。Java中,反射是一种强大的工具。它使您能够创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代表链接。反射允许我们在编写与执行时,使我们的程序代码能够接入装载到JVM中的类的内部信息,而不是源代码中选定的类协作的代码。这使反射成为构建灵活的应用的主要工具。但需注意的是:如果使用不当,反射的成本很高。
- Java 的这一能力在实际应用中也许用得不是很多,但是在其它的程序设计语言中根本就不存在这一特性。例如,Pascal、C 或者 C++ 中就没有办法在程序中获得函数定义相关的信息。
Java中的类反射
reflection的工作机制
- 承训运行时,java系统会一直对所有对象进行所谓的运行时类型识别,这项信息记录了每个对象所属的类。通过专门的类可以访问这些信息,用来保存这些信息的类是Class类,Class类为编写可动态操纵的java代码程序提供了强大的功能
构造Class类对象的三种方式
Class.forName
Class c = Class.forName("Emp"); System.out.println(c); //创建类的对象 Object obj = c.newInstamce(); System.out.println(obj);
类.class
//获取类对象的第二种方式 Class c1 = String.class; System.out.println(c1);
Object.getClass()
//获取类对象的第三种方式 String s = "123"; Class c2 = s.getClass(); System.out.println(c2);
Java反射中的主要类和方法
- 主要包:java.lang.reflect
- 主要类Class、Method、Field、Constructor、Modifier
反射案例—首先创建一个学生类
private String name;//私有属性
private static String address;//私有静态属性
public static String sex;//公开静态属性
public int age;//公开属性
public Student() {}//公开无参构造函数
public Student(String s) {}//公开带参构造函数
public Student(String s,int i) {}//公开带参构造函数
private Student(String s,int i,String s1) {}//私有带参构造函数
private void m1(){}//私有方法
private static void m2(){} //私有方法
private void m3(String s,int i){}//私有带参方法
public void m4(){}//公开方法
public static void m5(){} //公开静态方法
public int m6(String s,int i){
return 8;
}//公开带参、有返回值方法
Construcor
// 获取类对象
Class stuClass = Class.forName("p1.p2.Student");
// 获取类对象的公共构造方法
Constructor[] cs = stuClass.getConstructors();
// 获取类对象的所有构造方法(包括私有)
//cs = stuClass.getDeclaredConstructors();
System.out.println( cs.length );
for ( Constructor c : cs ) {
System.out.println( "构造方法的修饰符:" + Modifier.toString(c.getModifiers()) );
System.out.println( "构造方法的名称:" + c.getName() );
Class[] paramClasses = c.getParameterTypes();
for ( int i = 0; i < paramClasses.length; i++ ) {
Class clazz = paramClasses[i];
System.out.println( "\t第" +(i+1)+ "个参数类型:" + clazz.getName() );
}
System.out.println( "*****************************" );
}
//得到指定参数的公开的构造方法
Constructor c1 = stuClass.getConstructor(String.class);
//得到指定参数的私有的构造方法
Constructor c2 = stuClass.getDeclaredConstructor(String.class,int.class,String.class);
System.out.println(c1+"::::"+c2);
//通过类对象创建类的对象
Student s = (Student)stuClass.newInstance();
System.out.println(s);
//通过构造方法 创建类的对象
Student s1 = (Student)c1.newInstance("zhangsan");
System.out.println(s1);
Method
// 获取类对象
Class stuClass = Class.forName("p1.p2.Student");
// 获取类中所有的方法对象 获取不到父类的方法
Method[] ms = stuClass.getDeclaredMethods();
// 获取所有公共的方法对象 包括父类
//ms = stuClass.getMethods();
for (Method m : ms) {
System.out.println("方法的修饰符:" + Modifier.toString(m.getModifiers()));
System.out.println("方法的名称:" + m.getName());
Class[] paramClasses = m.getParameterTypes();
for (int i = 0; i < paramClasses.length; i++) {
Class clazz = paramClasses[i];
System.out
.println("\t第" + (i + 1) + "个参数类型:" + clazz.getName());
}
// 得到返回值
Class rtnClass = m.getReturnType();
System.out.println("方法的返回类型:" + rtnClass.getName());
System.out.println("*****************************");
}
Method m = stuClass.getMethod( "m5" );//根据方法名称得到公开的,无参的方法
m = stuClass.getMethod( "m6", String.class,int.class );//根据方法名称及参数得到公开的方法
System.out.println( "方法的修饰符:" + Modifier.toString(m.getModifiers()) );
if ( Modifier.isStatic(m.getModifiers())) {
m.invoke( null );
} else {
Object obj = stuClass.newInstance();
Object rtnVal = m.invoke( obj, "zhangsan",6 );
System.out.println( rtnVal );
}
Field
// 获取类对象
Class stuClass = Class.forName( "p1.p2.Student" );
// 获取属性对象
Field[] fs = stuClass.getFields();//返回所有属性 包括父类
//fs = stuClass.getDeclaredFields();
for ( Field f : fs ) {
System.out.println( "属性的修饰符:" + Modifier.toString(f.getModifiers()) );
System.out.println( "属性的名称:" + f.getName() );
System.out.println( "属性的类型:" + f.getType().getName() );
if(Modifier.isPrivate(f.getModifiers())){//如果是私有属性
f.setAccessible(true);//设置可访问
if ( Modifier.isStatic(f.getModifiers())) {
System.out.println( "属性的值:" + f.get( null ));
} else {
Object obj = stuClass.newInstance();
System.out.println( "属性的值:" + f.get( obj ));//返回指定对象上属性的值,不能访问私有
}
}
System.out.println("*************");
}
Class
// 获取类对象
Class sClass = Class.forName( "java.lang.String" );
// 类的修饰符
System.out.println( "类的修饰符:" + Modifier.toString(sClass.getModifiers()) );
System.out.println( "类的名称:" + sClass.getName() );
System.out.println( "类的简称:" + sClass.getSimpleName() );
System.out.println( "类的包:" + sClass.getPackage().getName() );
System.out.println( "类的父类:" + sClass.getSuperclass().getName() );
Class[] ifClasses = sClass.getInterfaces();
for ( Class c : ifClasses ) {
System.out.println( "类的接口:" + c.getName() );
}
System.out.println( "类是不是数组:" + sClass.isArray() );
安全性和反射
- 在处理反射时安全性是一个较复杂的问题。反射经常由框架型代码使用,由于这一点,我们可能希望框架能够全面接入代码,无需考虑常规的接入限制。但是,在其它情况下,不受控制的接入会带来严重的安全性风险,例如当代码在不值得信任的代码共享的环境中运行时。
反射的两个缺点
- 反射是一种强大的工具,但也存在一些不足。
- 性能问题,使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求,用于字段和方法接入时反射要远慢于直接代码,性能问题的成都取决于程序中是如何使用反射的,如果它作为程序运行中相对甚少涉及的部分,缓慢的性能将不会是一个问题。
- 使用反射会模糊程序内部实际要发生的事情,程序人员希望在源代码总看到程序的逻辑,反射等绕过了源代码的技术会带来维护问题,反射代码比相应的直接代码更复杂,解决这些问题的最佳方案是保护地使用反射,仅在它可以真正增加灵活性的地方–记录其在目标类中的使用。