TCP的三次握手:TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠。
(1)第一次握手,客户端向服务器端发出连接请求,等待服务器确认;
(2)第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求;
(3)第三次握手,客户端再次向服务器端发送确认信息,确认连接。
完成上述的三次握手后,客户端和服务器端的连接就已经建立了,每次连接的创建都需要经过“三次握手”的过程。
(1)UDP(用户数据报协议):
(1)UDP是无连接通信协议,在数据传输时,数据的发送和接收端不建立连接,也不能保证对方能接收成功。
(2)当一台计算机向另外一台计算机发送数据时(UDP),发送端不会确认接收端是否存在,就会直接发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。
(3)由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输,传输重要数据时不建议使用UDP协议,因为它不能保证数据传输的完整性。
(2)TCP(传输控制协议):
(1)TCP协议是面向连接的通信协议。
(2)传输数据之前,在发送端和接收端建立连接,然后再传输数据,它提供了两台计算机之间可靠的、无差错的数据传输。
(3)在TCP连接中,将计算机明确划分为客户端与服务器端,并且由客户端向服务端发出连接请求,每次连接的创建都需要经过“三次握手”的过程。
(3)TCP和UDP的区别:
//服务器端:
package com.briup.day23;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author chouhan
* 1.服务端需求:接收客户端发送过来的图片数据。进行存储后,回馈一个“上传成功”字样。
*/
public class TestServer {
public static void main(String[] args) throws IOException{
ServerSocket server=new ServerSocket(8899);
Socket socket=server.accept();
BufferedInputStream bi=new BufferedInputStream(socket.getInputStream());
BufferedOutputStream bo=new BufferedOutputStream(new FileOutputStream("C:\\Users\\Starg\\Desktop\\hzw.png"));
byte[] b=new byte[1024];
int len=-1;
while((len=bi.read(b))!=-1) {
bo.write(b,0,len);
}
bo.flush();
OutputStream out=socket.getOutputStream();
out.write("上传成功".getBytes());
bo.close();
socket.close();
}
}
//客户端:
package com.briup.day23;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
/**
* @author chouhan
* 2.客户端需求:把一个图片文件发送到服务端并读取回馈信息。
*/
public class TestClient {
public static void main(String[] args) throws IOException {
Socket socket=new Socket("127.0.0.1",8899);
BufferedInputStream bi=new BufferedInputStream
(new FileInputStream("C:\\Users\\Starg\\Desktop\\onepiece.png"));
BufferedOutputStream bo=
new BufferedOutputStream(socket.getOutputStream());
byte[] b=new byte[1024];
int len=-1;
while((len=bi.read(b))!=-1) {
bo.write(b,0,len);
}
bo.flush();
socket.shutdownInput();
System.out.println("上传结束");
InputStream in=socket.getInputStream();
byte[] b2=new byte[1024];
int len2=in.read(b2);
String data=new String(b2,0,len2);
System.out.println(data);
socket.close();
bi.close();
}
}
package com.briup.day23;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author chouhan
* 1.服务端需求:接收客户端发送过来的图片数据。进行存储后,回馈一个“上传成功”字样。
*/
public class TestServer {
public static void main(String[] args) throws IOException{
ServerSocket server=new ServerSocket(8899);
//1.同意连接
Socket socket=server.accept();
//2.把网络读取的文件保存到字节缓冲输入流
BufferedInputStream bi=new BufferedInputStream(socket.getInputStream());
//3.用字节缓冲输出流把网络输出流传到指定文件
BufferedOutputStream bo=new BufferedOutputStream(
new FileOutputStream("C:/Users/Starg/Desktop/hzw.png"));
//4.一点点把字节缓冲输入流读取到的文件传到字节缓冲输出流
int len=-1;
while((len=bi.read())!=-1) {
bo.write(len);
}
//5.读完字节缓冲输出流后刷新
bo.flush();
System.out.println("图片已完成接收");
//6.把网络输出流的信息传到字节打印输出流中
PrintStream ps=new PrintStream(socket.getOutputStream());
//7.给客户端提供一个反馈
ps.println("上传成功");
}
}
package com.briup.day23;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
/**
* @author chouhan
* 2.客户端需求:把一个图片文件发送到服务端并读取回馈信息。
*/
public class TestClient {
public static void main(String[] args) throws IOException {
//1.请求连接
Socket socket=new Socket("127.0.0.1",8899);
System.out.println("开始上传");
//2.把本地文件读到缓冲输入流中
BufferedInputStream bi=new BufferedInputStream
(new FileInputStream("C:/Users/Starg/Desktop/onepiece.png"));
//3.用字节缓冲输出流把文件写到网络文件
BufferedOutputStream bo=
new BufferedOutputStream(socket.getOutputStream());
//4.把字节缓冲输入流的文件一点点读到缓冲输出流
int len=-1;
while((len=bi.read())!=-1) {
bo.write(len);
}
//5.读完文件刷新
bo.flush();
//6.把网络输出流关闭
socket.shutdownOutput();
//7.用缓冲字符输入流读服务器端传过来的“上传成功”
BufferedReader br=new BufferedReader(
new InputStreamReader(socket.getInputStream()));
//8.打印上传成功
System.out.println(br.readLine());
}
}
总结:
(1)读取完文件后要刷新;
(2)客户端的网络传输完成后,socket要通过shutdownOutput()方法把输出流关闭;
(3)文件的读取和写入的文件路径必须存在且允许访问;
(4)缓冲流传递文件提高读写效率。