黑马程序员 网络(UDP传输和TCP传输)及反射

时间:2021-07-10 11:23:51
------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------


一.IP地址


每个设备在网络中的唯一标识

    每台网络终端在网络中都有一个独立的地址,我们在网络中传输数据就是使用这个地址。

    ipconfig:查看本机IP

    ping:测试连接

    本地回路地址:127.0.0.1255.255.255.255是广播地址

    IPv4:4个字节组成,4个0-255。大概42亿,30亿都在北美,亚洲4亿。2011年初已经用尽。

    IPv6:8组,每组4个16进制数。

    1a2b:0000:aaaa:0000:0000:0000:aabb:1f2f

    1a2b::aaaa:0000:0000:0000:aabb:1f2f

    1a2b:0000:aaaa::aabb:1f2f

    1a2b:0000:aaaa::0000:aabb:1f2f

    1a2b:0000:aaaa:0000::aabb:1f2f

二.端口号

每个程序在设备上的唯一标识

    每个网络程序都需要绑定一个端口号,传输数据的时候除了确定发到哪台机器上,还要明确发到哪个程序。

    端口号范围从0-65535

    编写网络应用就需要绑定一个端口号,尽量使用1024以上的,1024以下的基本上都被系统程序占用了。

    常用端口

    mysql: 3306

    oracle: 1521

    web: 80

    tomcat: 8080

    QQ: 4000

    feiQ: 2425

三.网络协议

为计算机网络中进行数据交换而建立的规则、标准或约定的集合。

    UDP

    面向无连接,数据不安全,速度快。不区分客户端与服务端。

    TCP

      面向连接(三次握手),数据安全,速度略低。分为客户端和服务端。

    三次握手: 客户端先向服务端发起请求, 服务端响应请求, 传输数据

四.Socket

通信的两端都有Socket。

    网络通信其实就是Socket间的通信。

    数据在两个Socket间通过IO流传输。

    Socket在应用程序中创建,通过一种绑定机制与驱动程序建立关系,告诉自己所对应的IP和port。


五.UDP传输

    1.发送

    创建DatagramSocket, 随机端口号

    创建DatagramPacket, 指定数据, 长度, 地址, 端口

    使用DatagramSocket发送DatagramPacket

    关闭DatagramSocket

    2.接收

    创建DatagramSocket, 指定端口号

    创建DatagramPacket, 指定数组, 长度

    使用DatagramSocket接收DatagramPacket

    关闭DatagramSocket

    从DatagramPacket中获取数据

    3.接收方获取ip和端口号

    String ip =packet.getAddress().getHostAddress();

    int port = packet.getPort();

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Scanner;

public class Demo2_Send {

/**
* 1.发送 创建DatagramSocket, 随机端口号 创建DatagramPacket, 指定数据, 长度, 地址, 端口
* 使用DatagramSocket发送DatagramPacket 关闭DatagramSocket
*
* @throws IOException
*/
public static void main(String[] args) throws IOException {
// String str = "我读书少,你不要骗我";
DatagramSocket socket = new DatagramSocket(); // 创建Socket对象,相当于创建码头
Scanner sc = new Scanner(System.in);
while (true) {
String line = sc.nextLine();
if("quit".equals(line))
break;
DatagramPacket packet = // 创建Packet对象,相当于创建集装箱
new DatagramPacket(line.getBytes(), line.getBytes().length,InetAddress.getByName("127.0.0.1"), 6666);
socket.send(packet); // 发送集装箱
}
socket.close();
}

}

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class Demo2_Receive {

/**
* 2.接收
创建DatagramSocket, 指定端口号
创建DatagramPacket, 指定数组, 长度
使用DatagramSocket接收DatagramPacket
关闭DatagramSocket
从DatagramPacket中获取数据
* @throws IOException
*/
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket(6666);//创建Socket对象,相当于创建码头
DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);//创建Packet对象,相当于创建集装箱接货
while(true) {
socket.receive(packet);//接收数据
byte[] arr = packet.getData();//获取数据
int len = packet.getLength();//获取有效的字节个数
String ip = packet.getAddress().getHostAddress();//获取ip地址
System.out.println(ip + ":" + new String(arr,0,len));
}
}

}


多线程

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Scanner;

public class Demo3_MoreThread {

/**
* @param args
*/
public static void main(String[] args) {
new Receive().start();
new Send().start();
}

}

class Receive extends Thread {
public void run() {
try {
DatagramSocket socket = new DatagramSocket(6666);//创建Socket对象,相当于创建码头
DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);//创建Packet对象,相当于创建集装箱接货
while(true) {
socket.receive(packet);//接收数据
byte[] arr = packet.getData();//获取数据
int len = packet.getLength();//获取有效的字节个数
String ip = packet.getAddress().getHostAddress();//获取ip地址
System.out.println(ip + ":" + new String(arr,0,len));
}
} catch (Exception e) {

e.printStackTrace();
}
}
}

class Send extends Thread {
public void run() {
try {
DatagramSocket socket = new DatagramSocket(); // 创建Socket对象,相当于创建码头
Scanner sc = new Scanner(System.in);
while (true) {
String line = sc.nextLine();
if("quit".equals(line))
break;
DatagramPacket packet = // 创建Packet对象,相当于创建集装箱
new DatagramPacket(line.getBytes(), line.getBytes().length,InetAddress.getByName("192.168.33.186"), 6666);
socket.send(packet); // 发送集装箱
}
socket.close();
} catch (Exception e) {

e.printStackTrace();
}
}
}

六.TCP传输

1.客户端

       创建Socket连接服务端(指定ip地址,端口号)通过ip地址找对应的服务器

       调用Socket的getInputStream()和getOutputStream()方法获取和服务端相连的IO流

       输入流可以读取服务端输出流写出的数据

       输出流可以写出数据到服务端的输入流


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class Demo2_Client {

/**
*1.客户端
创建Socket连接服务端(指定ip地址,端口号)通过ip地址找对应的服务器
调用Socket的getInputStream()和getOutputStream()方法获取和服务端相连的IO流
输入流可以读取服务端输出流写出的数据
输出流可以写出数据到服务端的输入流
* @throws Exception
* @throws UnknownHostException
*/
public static void main(String[] args) throws Exception {
Socket socket = new Socket("127.0.0.1", 12345);//创建客户端
/*InputStream is = socket.getInputStream();//获取输入流
OutputStream os = socket.getOutputStream();//获取输出流

byte[] arr = new byte[1024];
int len = is.read(arr);//读取服务器发送的数据
System.out.println(new String(arr,0,len));

os.write("学习挖掘机哪家强".getBytes());//将数据写给服务器
*/
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));//包装字节输入流
//BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
PrintStream ps = new PrintStream(socket.getOutputStream());//包装字节输出流
System.out.println(br.readLine());//读取服务器写过来的内容
ps.println("我要报名就业班");//将数据写给服务器
System.out.println(br.readLine())
ps.println("不学了");
//bw.write("我要报名就业班");
socket.close();
}

}

2.服务端

       创建ServerSocket(需要指定端口号)

       调用ServerSocket的accept()方法接收一个客户端请求,得到一个Socket

       调用Socket的getInputStream()和getOutputStream()方法获取和客户端相连的IO流

       输入流可以读取客户端输出流写出的数据

       输出流可以写出数据到客户端的输入流

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Demo2_Server {

/**
* 2.服务端
创建ServerSocket(需要指定端口号)
调用ServerSocket的accept()方法接收一个客户端请求,得到一个Socket
调用Socket的getInputStream()和getOutputStream()方法获取和客户端相连的IO流
输入流可以读取客户端输出流写出的数据
输出流可以写出数据到客户端的输入流
* @throws Exception
*/
public static void main(String[] args) throws Exception {
ServerSocket server = new ServerSocket(54321);//创建服务端,绑定54321端口
Socket socket = server.accept();//接受客户端请求
/*InputStream is = socket.getInputStream();//获取字节输入流
OutputStream os = socket.getOutputStream();//获取字节输出流

os.write("百度一下你就知道".getBytes());//将内容写给客户端

byte[] arr = new byte[1024];
int len = is.read(arr);//从客户端读取数据
System.out.println(new String(arr,0,len));*/
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));//包装字节输入流
//BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

//bw.write("欢迎咨询传智播客");
PrintStream ps = new PrintStream(socket.getOutputStream());//包装字节输出流,因为里面有一个println的方法
ps.println("欢迎咨询传智播客");//将字符串写到客户端
System.out.println(br.readLine());//读取客户端发过来的信息
ps.println("报满了,等下一期吧");
System.out.println(br.readLine());
server.close();
socket.close();
}

}

创建多线程的服务端,可以不断的向服务端访问

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Demo3_MoreThread {

/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(12345);
while(true) {
final Socket socket = server.accept();//不断的接收客户端的请求
new Thread() {
public void run() {
try {
BufferedReader br =
new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream ps = new PrintStream(socket.getOutputStream());

ps.println("欢迎咨询黑马程序员");
System.out.println(br.readLine());
ps.println("不一万就业不给一分钱");
System.out.println(br.readLine());
ps.println("不学拉到");
socket.close();
} catch (Exception e) {

e.printStackTrace();
}
}
}.start();
}
}

}

七.反射

1.Class

       .class文件加载到内存中就是一个Class对象

       获取Class对象的方式有3种:

       Scanner sc = newScanner("xxx.txt");

           Class.forName(sc.nextLine());

           类名.class

           对象.getClass()

import cn.itcast.bean.Person;

public class Demo1_Reflect {

/**
* @param args
* @throws ClassNotFoundException
*/
public static void main(String[] args) throws ClassNotFoundException {
Class<?> clazz1 = Class.forName("cn.itcast.bean.Person");
Class<?> clazz2 = Person.class;

Person p = new Person();
Class<?> clazz3 = p.getClass();

System.out.println(clazz1 == clazz2);
System.out.println(clazz2 == clazz3);
}

}

2.Constructor

       Class类的newInstance()方法是使用该类无参的构造函数创建对象, 如果一个类没有无参的构造函数, 就不能这样创建了

       可以调用Class类的getConstructor(String.class,int.class)方法获取一个指定的构造函数

       然后再调用Constructor类的newInstance("张三",20)方法创建对象

import java.lang.reflect.Constructor;

import cn.itcast.bean.Person;

public class Demo3_Constructor {

/*
@throws Exception
*/
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("cn.itcast.bean.Person");
/*Person p = (Person) clazz.newInstance();
System.out.println(p);*/
Constructor con = clazz.getConstructor(String.class,int.class);//获取有参的构造函数
Person p = (Person) con.newInstance("张三",23);//创建对象
System.out.println(p);//打印对象
}

}

3.Field

       Class.getField(String)方法可以获取类中的指定字段(可见的), 如果是私有的可以用getDeclaedField("name")方法获取

       通过set(obj, "李四")方法可以设置指定对象上该字段的值, 如果是私有的需要先调用setAccessible(true)设置访问权限

       用获取的指定的字段调用get(obj)可以获取指定对象中该字段的值

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

import cn.itcast.bean.Person;

public class Demo4_Field {



public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("cn.itcast.bean.Person");
Constructor con = clazz.getConstructor(String.class,int.class);//获取有参的构造函数
Person p = (Person) con.newInstance("张三",23);//创建对象

/*Field f = clazz.getField("name");
System.out.println(f);*/
Field f = clazz.getDeclaredField("name");//暴力反射
f.setAccessible(true);//去除权限
f.set(p, "李四");
System.out.println(p);
}

4.Method

       Class.getMethod(String, Class...) 和 Class.getDeclaredMethod(String, Class...)方法可以获取类中的指定方法

       调用invoke(Object,Object...)可以调用该方法

       Class.getMethod("eat")invoke(obj) Class.getMethod("eat",int.class) invoke(obj,10)

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

import cn.itcast.bean.Person;

public class Demo5_Method {

/**
*4.Method
Class.getMethod(String, Class...) 和 Class.getDeclaredMethod(String, Class...)方法可以获取类中的指定方法
调用invoke(Object, Object...)可以调用该方法
Class.getMethod("eat") invoke(obj) Class.getMethod("eat",int.class) invoke(obj,10)
* @throws Exception
*/
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("cn.itcast.bean.Person");
Constructor con = clazz.getConstructor(String.class,int.class);//获取有参的构造函数
Person p = (Person) con.newInstance("张三",23);//创建对象

Method m = clazz.getMethod("eat");
m.invoke(p);

Method m2 = clazz.getMethod("eat", int.class);
m2.invoke(p, 10);
}

}