一
IPv4地址分类
端口号
网络通信协议
在网络编程中,数据的组织形式就是协议
TCP UDP 协议
InetAddress类
public static void main(String[] args) throws UnknownHostException {
InetAddress localHost = InetAddress.getLocalHost();//获取本机的InetAddress对象(主机名和IP地址)
System.out.println(localHost);
InetAddress byName = InetAddress.getByName("DESKTOP-Ding");//指定主机名,获取InetAddress对象(主机名和IP地址)
System.out.println(byName);
InetAddress byName1 = InetAddress.getByName("www.baidu.com");//根据域名,获取InetAddress对象(域名和IP地址)
System.out.println(byName1);
String hostAddress = localHost.getHostAddress();//反向获取IP地址
System.out.println(hostAddress);
String hostName = byName1.getHostName();//反向获取域名
System.out.println(hostName);
}
//输出
DESKTOP-Ding/169.254.159.192
DESKTOP-Ding/169.254.159.192
www.baidu.com/110.242.68.3
169.254.159.192
www.baidu.com
Socket套接字(TCP)
socket位于数据通道两端,两端都有socket.getInputSteam(输入流)和socket.getOutputStream(输出流),一端输出另一端就输入。服务器处于监听状态,时刻等待客户端的链接
两种编程方式:
1.TCP编程
2.UDP编程
代码实现(字节流)
服务器一定要先开启服务,等待客户端的链接
本地主机Host
public class Host {//本地主机
public static void main(String[] args) throws IOException {
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);//设置服务器的IP地址,主机名和端口号
OutputStream outputStream = socket.getOutputStream();
outputStream.write("hi server".getBytes());//向服务器发送内容
socket.shutdownOutput();//输出结束标记 结束服务器等待
InputStream inputStream = socket.getInputStream();
byte[] bytes = new byte[1024];
int read = 0;
while((read = inputStream.read(bytes))!= -1){
System.out.println(new String(bytes,0,read));//接受服务器的信息
}
//关闭资源,避免浪费
outputStream.close();
inputStream.close();
socket.close();
}
}
服务器Server
public class Server {//服务器
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(9999);//设置服务器对应端口号
System.out.println("等待链接:");
Socket accept = serverSocket.accept();//通道监听
InputStream inputStream = accept.getInputStream();
byte[] bytes = new byte[1024];
int read = 0;
while((read = inputStream.read(bytes))!=-1){//接受主机发送的信息
System.out.println(new String(bytes,0,read));
}
OutputStream outputStream = accept.getOutputStream();
outputStream.write("已接受".getBytes());//向主机发送信息
accept.shutdownOutput();//输出结束标记
//关闭资源,避免浪费
outputStream.close();
serverSocket.close();
accept.close();
}
}
代码实现(字符流)
本地主机Host
public class Host {//本地主机
public static void main(String[] args) throws IOException {
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);//设置服务器的IP地址,主机名和端口号
//使用字符输出流输出信息
OutputStream outputStream = socket.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write("hello");
bufferedWriter.newLine();//插入换行符,表示写入内容结束。对方需要readLine()接受
bufferedWriter.flush();//使用字符流手动刷新才能进入通信通道
//使用字符输入流接收信息
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();//通过readLine()接受信息
System.out.println(s);
//关闭资源,避免浪费
bufferedReader.close();
bufferedWriter.close();
socket.close();//通道关闭
}
}
服务器Server
public class Server {//服务器
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(9999);//设置服务器对应端口号
System.out.println("等待链接:");
Socket socket = serverSocket.accept();//通道监听
//使用字符输入流接受客户端信息
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();//readLine()接受
System.out.println(s);
//使用字符输出流输出信息
OutputStream outputStream = socket.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write("hi");
bufferedWriter.newLine();//输出信息结束标记
bufferedWriter.flush();//字符输出流手动刷新才可进入通信通道
//关闭资源,避免浪费
bufferedWriter.close();
bufferedReader.close();
serverSocket.close();//服务器对象关闭
socket.close();//通信通道关闭
}
}
netstat(DOS命令)
UDP网络通信编程 (了解)
不指定发送端口,但是两端得指定接收端口
代码实现
接收端
public class Receive {//接收端A
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket(9999);//创建接收对象的接口
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);//创建通道
//调用接收方法,将通过网络传输的DatagramPacket对象,填充到packet
socket.receive(packet);
//可以把packet进行拆包,取出数据并显示
int length = packet.getLength();//实际收到的数据长度
byte[] data = packet.getData();//实际收到的数据
String s = new String(data, 0, length);
System.out.println(s);
socket.send(packet);//发送
//回复信息给B端
data = "Hi".getBytes();
packet = new DatagramPacket(data, data.length, InetAddress.getLocalHost(),9998);
socket.close();//关闭资源
}
}
发送端
public class Send {//发送端B
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket(9998);//创建DatagramSocket对象,在9998端口接收数据
//将需要发送的数据封装到DatagramPacket对象
byte[] data = "hello".getBytes();
DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getLocalHost(),9999);
socket.send(packet);//发送
//接收A端消息
byte[] buf = new byte[1024];
packet = new DatagramPacket(buf, buf.length);//创建通道
//调用接收方法,将通过网络传输的DatagramPacket对象,填充到packet
socket.receive(packet);
//可以把packet进行拆包,取出数据并显示
int length = packet.getLength();//实际收到的数据长度
data = packet.getData();//实际收到的数据
String s = new String(data, 0, length);
System.out.println(s);
socket.send(packet);//发送
socket.close();//关闭资源
}
}
多用户通信系统演示
项目开发流程
二
反射
动态代理:无侵入式的给代码增加额外的功能。对象如果嫌身上的干的事太多,可以通过代理来转移部分职责。 对象有什么方法想被代理。代理就一定要有对应的方法
获取类对象
如何获取类对象
Person类
public class Person {
String name;
int age;
public void eat(){
System.out.println(name + age+"吃饭");
}
//无参构造器
public Person() {
}
//有参构造器
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
TestPerson类
推荐使用第三种方法,依赖性相对较弱
public class TestPerson {
public static void main(String[] args) throws Exception {
getClazz();
}
public static void getClazz() throws ClassNotFoundException {
//使用对象获取类对象
Person zhangsan = new Person();
Class<?> class1 =zhangsan.getClass();
System.out.println(class1.toString());
//使用类名.class属性 【推荐使用】
Class<?> class2 = Person.class;
System.out.println(class2.toString());
//使用Class的静态方法
Class<?> class3 = Class.forName("reflect.Person");
System.out.println(class3.toString());
}
}
与反射相关的常用方法
使用反射获取类的构造方法并创建实例
public static void refelctOp1() throws ClassNotFoundException {
Class<?> class1 = Class.forName("reflect.Person");
Constructor<?>[] constructors = class1.getConstructors();
for (Constructor<?> o :constructors) {//遍历
System.out.println(o.toString());
}
}
在主方法运行 输出结果。
public reflect.Person(java.lang.String,int)
public reflect.Person()
public static void refelctOp1() throws Exception {
Class<?> class1 = Class.forName("reflect.Person");
//获取类中无参构造
Constructor<?> con = class1.getConstructor();
Person person1 = (Person) con.newInstance();//创建一个实例
System.out.println("person1:"+person1.toString());
//简便方法 类对象.newInstance()
Person person2 =(Person) class1.newInstance();//使用了强制转换 Object person2 =class1.newInstance()
System.out.println("person2:"+person2.toString());
//获取类中带参构造
Constructor<?> con2 = class1.getConstructor(String.class, int.class);
Person jack =(Person) con2.newInstance("jack", 20);
System.out.println(jack);
}
主方法运行 输出结果。
person1:Person{name='null', age=0}
person2:Person{name='null', age=0}
Person{name='jack', age=20}
使用反射获取类中的方法并调用
调用使用invoke()方法,第一个参数调用方法的对象,第二个是方法的参数
public static void refelctOp2() throws Exception{
Class<?> class1 = Class.forName("reflect.Person");
Method[] methods = class1.getMethods();// getMethods()只获取类中公开的方法,包括从父类继承的方法
Method[] declaredMethods = class1.getDeclaredMethods();//getDeclaredMethods获取类中所有方法,不包含继承的
for (Method method :declaredMethods) {
System.out.println(method.toString());
}
//获取无参的方法并调用
Method methods = class1.getMethod("eat");
Person P1 =(Person) class1.newInstance();//创建类的实例对象
methods.invoke(P1);//调用方法 相当于 P1.eat()
//获取toString方法并调用
Method toString = class1.getMethod("toString");
Object invoke = toString.invoke(P1);//有返回值,需要接受
System.out.println(invoke);
//获取带参方法并调用
Method eat = class1.getMethod("eat", String.class);
eat.invoke(P1, "鸡腿");
//获取私有方法并调用
Method privateMethod = class1.getDeclaredMethod("privateMethod");
privateMethod.setAccessible(true);//调用时有私有访问限制,设置私有访问无效
privateMethod.invoke(P1);
//获取静态方法并调用
Method staticMethod = class1.getMethod("staticMethod");
staticMethod.invoke(null);
}
输出结果
null0吃饭
Person{name='null', age=0}
null吃鸡腿
这是私有方法
这是静态方法
方法
public class Person {
String name;
int age;
public void eat(){
System.out.println(name + age+"吃饭");
}
public void eat(String food){
System.out.println(name + "吃"+food);
}
private void privateMethod(){
System.out.println("这是私有方法");
}
public static void staticMethod(){
System.out.println("这是静态方法");
}
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
使用反射获取类中所有方法的通用方法
ublic class TestPerson {
public static void main(String[] args) throws Exception {
Person person = new Person();
//person.eat("米饭");
invokeAny(person,"eat",new Class[]{String.class},"米饭" );
}
public static Object invokeAny(Object obj,String methodName,Class<?>[] types,Object...args) throws Exception{
Class<?> class1 = obj.getClass();//获取类对象
Method method = class1.getMethod(methodName, types);//通过反射调用方法,方法名字和参数
return method.invoke(obj,args);//调用
}
}
该方法
public void eat(String food){
System.out.println(name + "吃"+food);
}
输出结果
null吃米饭
使用反射获取类中的属性
public static void md() throws Exception {
Class<?> class1 = Class.forName("reflect.Person");
//获取属性公开的,包括父类继承的
Field[] field = class1.getFields();
//获取所有属性,包括私有,保护和默认,不包含继承
Field[] declaredFields = class1.getDeclaredFields();
for (Field field1 :declaredFields) {
System.out.println(field1.toString());
}
//获取单个属性
Field name = class1.getDeclaredField("name");//获取name属性
//name.setAccessible(true);//若属性为私有,则设置访问权限无效即可
Person P1 = (Person) class1.newInstance();//Person P1 = new Person()
name.set(P1,"张三");//P1.name = "张三"
System.out.println("name"+name.get(P1));//获取输出
}
输出
java.lang.String reflect.Person.name
int reflect.Person.age
name张三