网络编程
害,人和人和差别比人和猪的差别还大,我算是见识到了,大佬太多了,自己真菜狗哭了
笔记
TCP/IP四层概念模型
应用层,http,ftp,smtp,dns
传输层,tcp,udp
网络层,ip
数据链路层网络编程中有两个主要问题
1,如何准确定位到网络上的一台电脑,ip和端口
2,找到主机后如何进行通信,网络通信协议tcp/udp
IP,InetAddress类使用静态方法创建对象,工具类
方法:
InetAddress address = InetAddress.getByName("keyi.world"),返回一个指定IP对象
address.getHostAddress(),返回主机ip地址字符串
address.getHostName,返回域名,或者自己电脑名称字符串
端口:区分计算机不同的软件,0-65535
tcp协议和udp协议分别都有0-65535端口号,同一协议下,端口号不同相同
端口分类:
公有端口:操作系统自身使用,0-1023
程序注册端口:用户端口,1024-49151
tomcat:8080
mysql:3306
动态,私有端口,49152-65535
查看电脑所有端口命令:netstat -ano
查看指定的端口命令:netstat -ano|findstr "8080"
udp
udp是一种不可靠的网络协议,它在通信两端各建立一个socket对象,
但这两个socket只是发送和接收的对象,udp不存在客户端和服务器的概念
java提供了DatagramSocket类作为基于udp协议的socket
udp发送端步骤:
1,创建DatagramSocket对象
DatagramSocket socket = new DatagramSocket();
2,创建数据,并把数据打包,DatagramPacket,数据报包
DatagramPacket packet = new DatagramPacket(bytes,bytes.length,
InetAddress.getByName("localhost"),10086);
3,调用socket对象send方法发送数据
socket.send(packet);
4,关闭socket对象
socket.close();
udp接收端:
1,创建DatagramSocket对象,绑定端口
DatagramSocket socket = new DatagramSocket(10086);
2,创建数据报包DatagramPacket,指定字节数组保存数据
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
3,调用socket对象的receive方法接收数据
socket.receive(packet);
4,展示数据并关闭socket
byte[] data = packet.getData();
System.out.println(new String(data));
socket.close();
tcp
tcp是可靠的网络协议,需要经过三次握手四次挥手才会建立连接
三次握手,四次挥手:
三次握手
1.客户端向服务端发送请求,一次,表明自己发送能力没问题,
2.但客户端不知道服务端有没有收到消息,所以服务端发送消息给客户端,二次,表明自己已收到消息,
3.客户端接收后,就知道,服务端接收能力没问题,发送能力没问题,
但服务端还不知道客户端有没有接收到消息,所以,客户端再次发送消息给服务端,三次,
表示自己已收到,证明自己接收能力没有问题
四次挥手
1.客户端发送请求给服务端,表示自己要断开连接,自己已经不会再发送数据了,
但如果还有数据没接收完,服务端可以继续发给我,挥手一次,
2.服务端收到第一次挥手后,就会发送消息给客户端,表示服务端已经知道了,
等我数据发送完再通知你,挥手二次,
3.服务端发送完全部数据后,再次发送消息给客户端,我数据处理完了,
此时服务端进入等待,等待客户端发消息,挥手三次,
4.客户端接收到消息,就知道,服务端已经把数据全部发给我了,此时可以断开了,
客户端再次发消息给服务端,彻底断开连接,挥手四次
tcp客户端:
1,创建socket对象,指定服务器的地址和端口号
Socket socket = new Socket("localhost",10086);
2,通过socke获取字节输入流/字节输出流,从而向socket中读取/写入数据
BufferReader read = new BufferedReader(new
FileReader("C:\\Users\\OneForAll\\Desktop\\IDEA快捷键.txt"));
BufferReader reader = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
BufferedWriter writer = new BufferedWriter(new
OutputStreamWriter(socket.getOutputStream()));
String data;
while ((data= read.readLine())!=null){
writer.write(data);
writer.newLine();
writer.flush();
}
3,关闭socket
tcp服务端:
1,创建服务端套接字对象,绑定端口
ServerSocket serverSocket = new ServerSocket(10086);
2,serverSocket对象等待接收客户端的请求从而获得socket对象,是个阻塞方法
Socket socket = serverSocket.accept();
3,通过socket对象获取输入输出流来传输数据
4,关闭socket
注解
注解Annotation是一种引用类型,编译之后也是生成xxx.class文件
创建语法格式:
修饰符列表 @interface 注解类型名{
}
使用格式:@注解类型名
使用地方:类上,属性上,方法上,变量上,注解还可以出现在注释上
jdk内置了哪些注解?
java.lang包下有三个注解:
@Deprecated,表示过时的,废弃的
@override,表示重写的方法,标识性注解,给编译器做检查,只在编译时期起作用,跟运行期无关
@SuppressWarnings
元注解:修饰注解的注解就是元注解
常见的元注解:
Target,用来标注注解的使用范围,例如Target(ElementType.METHOD),只能出现在方法上
Retention,用来标注注解最终保存在哪里,例如
@Retention(RetentionPolicy.SOURCE),该注解只被保留在源文件中
@Retention(RetentionPolicy.CLASS),该注解被保存在class文件中
@Retention(RetentionPolicy.RUNTIME),该注解被保存在class文件中,并可以被反射机制所读取
注解定义属性:
public @interface MyAnnotation {
//这是注解的name属性,如果注解有属性则使用时必须给属性赋值,除非该属性使用default指定了默认值
String name() default "";
}
如果注解中只有一个属性,且属性名为value,则使用注解时,属性名可以省略
public @interface MyAnnotation {
//这是注解的name属性
String name();
int[] age(); //属性的类型可以是八大类型加上String,Class和枚举,以及他们的数组都可以
}
public class Test {
//@MyAnnotation(name="Coco",age ={20,25})
@MyAnnotation(name="Coco",age = 20) //数组只有一个值的话,大括号可以省略
public void show(){
System.out.println("show time");
}
}
注意:如果注解中属性是数组类型,且数组中只有一个值,则大括号可以省略
通过反射得到注解中属性值:
1,获取被注解类的字节码对象
Class<?> aClass = Class.forName("keyi.world.annotation.Test");
2,如果注解在方法上,则通过反射获取该方法对象
Method show = aClass.getMethod("show");
3,if判断是否有定义的注解
if(aClass.isAnnotationPresent(MyAnnotation.class)){} //注解在类上
if(show.isAnnotationPresent(MyAnnotation.class)){} //注解在方法上
4,得到注解对象
MyAnnotation annotation = aClass.getAnnotation(MyAnnotation.class);
MyAnnotation annotation = show.getAnnotation(MyAnnotation.class);
5,像调用方法一样,获取注解属性
System.out.println(annotation.name());
网络编程代码
UDP
发送端: public class SendUDP { public static void main(String[] args) { DatagramSocket socket=null; BufferedReader reader=null; try { socket = new DatagramSocket(); reader = new BufferedReader(new InputStreamReader(System.in)); InetAddress address = InetAddress.getByName("localhost"); String data =null; while((data=reader.readLine())!=null){ if(data.equals("886")){ break; } DatagramPacket packet = new DatagramPacket(data.getBytes(),data.getBytes().length, address,3800); socket.send(packet); } } catch (IOException e) { e.printStackTrace(); }finally { try { if (reader != null) { reader.close(); } } catch (IOException e) { e.printStackTrace(); } if (socket != null) { socket.close(); } } } } 接收端: public class ReceiveUDP { public static void main(String[] args) { DatagramSocket socket=null; try { socket = new DatagramSocket(3800); while (true){ byte[] bytes = new byte[1024]; DatagramPacket packet = new DatagramPacket(bytes, bytes.length); socket.receive(packet); byte[] data = packet.getData(); System.out.println(new String(data)); } } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { if (socket != null) { socket.close(); } } } }
TCP
客户端: public class FileClientTCP { public static void main(String[] args) { /* * 功能:客户端发送文件给服务端,服务端接收后保存下来,并给客户端反馈 * 服务端使用多线程,可以同时接受多个客户端的请求 * */ Socket socket=null; BufferedReader read=null; BufferedReader reader; BufferedWriter writer; try { socket = new Socket("localhost",10086); read = new BufferedReader(new FileReader("C:\\Users\\OneForAll\\Desktop\\IDEA快捷键.txt")); reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); String data; while ((data= read.readLine())!=null){ writer.write(data); writer.newLine(); writer.flush(); } socket.shutdownOutput(); while ((data= reader.readLine())!=null){ System.out.println("服务端发来消息:"+data); } }catch (IOException e) { e.printStackTrace(); }finally { if (read!=null){ try { read.close(); } catch (IOException e) { e.printStackTrace(); } } if (socket != null) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } } 服务端 public class FileServerThreadTCP implements Runnable { private Socket socket; public FileServerThreadTCP(Socket socket) { this.socket = socket; } @Override public void run() { BufferedWriter writer = null; BufferedReader reader = null; PrintStream printStream = null; try { //服务端多线程解决写入文件时重复名问题 int count = 0; File file = new File("C:\\Users\\OneForAll\\Desktop\\IDEA快捷键 [" + count + "].txt"); while (file.exists()) { count++; file = new File("C:\\Users\\OneForAll\\Desktop\\IDEA快捷键 [" + count + "].txt"); } writer = new BufferedWriter(new FileWriter(file)); reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); printStream = new PrintStream(socket.getOutputStream(), true); String data; while ((data = reader.readLine()) != null) { writer.write(data); writer.newLine(); writer.flush(); } printStream.println("文件上传成功"); } catch (IOException e) { e.printStackTrace(); } finally { if (printStream != null) { printStream.close(); } if (writer != null) { try { writer.close(); } catch (IOException e) { e.printStackTrace(); } } try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } 服务端启动 public class ThreadTCP { public static void main(String[] args) { try { ServerSocket serverSocket = new ServerSocket(10086); while (true){ Socket socket = serverSocket.accept(); new Thread(new FileServerThreadTCP(socket)).start(); } } catch (IOException e) { e.printStackTrace(); } } }