网络协议
协议:规范 合同
1.udp:非面向连接的(写信可以一直向对方地址不停的发送),不安全,效率高,协议简单,开销小,大小有限制一般不超过60K
2.tcp:面向连接的(打电话,需要对方也接通电话才可以),安全,效率低,开销大.
三次握手原理:1.拨号:发送请求 2.回访:响应请求 3.发送数据,基于io传出数据
后台应用层如何与传输层进行沟通
1.通过Socket套接字
2.面向Socket编程,Socket相当于插座,是两层之间沟通的接口,不同协议,Socket的实现不一样
udp实现Socket编程:发送端和接受端处于平等沟通
1.DatagramSocket 此类表示用来发送和接受数据报包的套接字
new DatagramSocket(int port) //创建发送端并给发送端设定一个端口
2.DatagramPacket 此类表示数据报包
/*参数 1.通过字节数组包装好的数据
2.字节数组开始索引
3.字节数组结束索引
4.需要发送到的地址( InetSocketAddress类(IP地址+端口号))
5.通过DatagramSocket类中的方法send(new DatagramPacket)将包发送出去
*/
new DatagramPacket(byte[] buf, int offset, int length, SocketAddress address)
UDP基本流程:发送端
1.创建发送端,指名发送端的端口
2.准备数据,转为字节数组
3.把数据大包,指名接收端的地址和端口号 new DatagramPacket(byte[] buf, int offset, int length, SocketAddress address)
4.发送数据( DatagramSocket类中的方法send(new DatagramPacket))
5.关闭资源(流)
public class SendDemo01 {
public static void main(String[] args) throws IOException {
System.out.println("----------------发送端--------------");
//1,创建发送端
DatagramSocket socket=new DatagramSocket(8888);
//2.准备数据,转为字节数组
String str="那些你很冒险的梦";
byte[] arr=str.getBytes();
//3.打包 DatagramPacket(byte[] buf, int offset, int length, SocketAddress address)
DatagramPacket packet=new DatagramPacket(arr,0,arr.length,new InetSocketAddress("localhost",9999));
//4.void send(DatagramPacket p) 从此套接字发送数据报包。
socket.send(packet);
//5.关闭
socket.close();
}
}
UDP基本流程:接收端
1.构建接收端,指定接收端端口
2.准备字节数组用来存储接受数据的
3.把字节数组打包
4.阻塞式接收
5.处理数据
6.关闭
public class ReceiveDemo02 {
public static void main(String[] args) throws IOException {
System.out.println("----------------接受端--------------");
//1.构建接受端,指定接受端端口
DatagramSocket socket=new DatagramSocket(9999);
//2.准备字节数组,用来存储接口收据的
byte[] arr=new byte[1024*60];
//3.把字节数组打包 DatagramPacket(byte[] buf, int offset, int length)
DatagramPacket packet=new DatagramPacket(arr,0,arr.length);
//4.接收 void receive(DatagramPacket p) 从此套接字接收数据报包。
socket.receive(packet);
/*
* byte[] getData() 返回数据缓冲区。
int getLength() 返回将要发送或接收到的数据的长度。
*/
//5.处理数据
System.out.println(new String(packet.getData()));
System.out.println(packet.getLength());
//6.关闭
socket.close();
}
}
UDP基本流程文件传输:发送端
1.创建发送端,指名发送端的端口
2.从文件中读取数据,字节数组
3.把字节数组大包 指名接受端的地址和端口号
4.发送数据
5.关闭
public static void main(String[] args) throws IOException {
System.out.println("----------------发送端--------------");
//1,创建发送端
DatagramSocket socket=new DatagramSocket(8888);
//2.准备数据,转为字节数组
//文件输入流
InputStream is=new FileInputStream("D://hehe.txt");
byte[] car=new byte[6];
int len;
//文件读写
while((len=is.read(car))!=-1){
//3.打包 DatagramPacket(byte[] buf, int offset, int length, SocketAddress address)
DatagramPacket packet=new DatagramPacket(car,0,len,new InetSocketAddress("localhost",9999));
//4.void send(DatagramPacket p) 从此套接字发送数据报包。
socket.send(packet);
}
//结束判断
byte[] end="bye".getBytes();
DatagramPacket packet=new DatagramPacket(end,0,end.length,new InetSocketAddress("localhost",9999));
//4.void send(DatagramPacket p) 从此套接字发送数据报包。
socket.send(packet);
//5.关闭
is.close();
socket.close();
}
}
UDP基本流程:接受端
1.构建接受端,指定接受端端口
2.准备字节数组,用来储存接口收据的
3.把字节数组打包
4.阻塞式接受
5.处理数据,把数据接入文件中
6.关闭
public class ReceiveDemo04 {
public static void main(String[] args) throws IOException {
System.out.println("----------------接受端--------------");
//1.构建接受端,指定接受端端口
DatagramSocket socket=new DatagramSocket(9999);
//2.准备字节数组,用来存储接口收据的
byte[] arr=new byte[6];
//3.把字节数组打包 DatagramPacket(byte[] buf, int offset, int length)
DatagramPacket packet=new DatagramPacket(arr,0,arr.length);
//4.接收 void receive(DatagramPacket p) 从此套接字接收数据报包。
OutputStream out=new FileOutputStream("/src/dest.txt"); //绝对路径:以盘符开头,以/开头(当前项目所在盘符+/后跟的路径)
boolean flag=true;
while(flag){
socket.receive(packet);
//5.处理数据
byte[] car=packet.getData();
int len=packet.getLength();
if(new String(car,0,len).equals("bye")){
System.out.println("结束了");
break;
}
out.write(car, 0,len);
}
//6.关闭
out.flush();
out.close();
socket.close();
}
}
tcp实现Socket编程,是客户端(Socket)和服务端(ServerSocket)之间不对等沟通(客户端必须要服务器处于开启状态);
tcp基本流程:客户端
public class Client01 {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("------------Client-----------");
//1.创建客户端 Socket 指定服务端的ip和端口
Socket client=new Socket("127.0.0.1",9999);
//2.io操作 OutputStream getOutputStream() 返回此套接字的输出流。
DataOutputStream out=new DataOutputStream(new BufferedOutputStream(client.getOutputStream()));
out.writeUTF("name=hangsan&pwd=123");
//3.关闭
out.flush();
out.close();
client.close();
}
}
tcp基本流程:服务端
public class Server02 {
public static void main(String[] args) throws IOException {
System.out.println("------------Server-----------");
// 1.构建服务端 ServerSocket 指定端口
ServerSocket server=new ServerSocket(9999);
// 2.阻塞式监听
Socket socket=server.accept();
System.out.println("一个客户端连接成功");
// 3.一个客户端就是一个socket IO操作
DataInputStream is=new DataInputStream(new BufferedInputStream(socket.getInputStream()));
String str=is.readUTF();
System.out.println(str);
// 4.关闭
is.close();
socket.close();
server.close();
}
}
tcp单向登录基本流程:客户端
public class LoginClient03 {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("------------Client-----------");
//用户输入 先创建流 再接受需要的数据
BufferedReader read=new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入用户名:");
String name=read.readLine();
System.out.println("请输入用密码:");
String pwd=read.readLine();
//1.创建客户端 Socket 指定服务端的ip和端口
Socket client=new Socket("127.0.0.1",9999);
//2.io操作 OutputStream getOutputStream() 返回此套接字的输出流。
DataOutputStream out=new DataOutputStream(new BufferedOutputStream(client.getOutputStream()));
out.writeUTF("name="+name+"&pwd="+pwd);
//3.关闭
out.flush();
out.close();
client.close();
}
}
tcp单向登录基本流程:服务端
public class LoginServer04 {
public static void main(String[] args) throws IOException {
System.out.println("------------Server-----------");
// 1.构建服务端 ServerSocket 指定端口
ServerSocket server=new ServerSocket(9999);
// 2.阻塞式监听
Socket socket=server.accept();
System.out.println("一个客户端连接成功");
// 3.一个客户端就是一个socket IO操作
DataInputStream is=new DataInputStream(new BufferedInputStream(socket.getInputStream()));
String str=is.readUTF();
System.out.println(str);
String[] arr=str.split("&"); //name=zhangsan pwd=123
String name="";
String pwd="";
for(String s:arr){
String[] arrr=s.split("=");
if(arrr[0].equals("name")){
name=arrr[1];
}else if(arrr[0].equals("pwd")){
pwd=arrr[1];
}
}
if("laopei".equals(name) && "123".equals(pwd)){
System.out.println("登录成功");
}else{
System.out.println("用户名或密码有误");
}
// 4.关闭
is.close();
socket.close();
server.close();
}
}