在传输层,UDP和TCP是最主要的协议
1、UDP
UDP报文没有可靠性保证、顺序保证和流量控制字段,同时提高了传输效率,主要用于不强制要求可靠性的数据传输,比如视频流等。
Java的基于UDP的socket:文件传输
代码示例:
//接受方代码:
public static void server(){
try {
FileOutputStream out = new FileOutputStream(new File("C:\\Users\\lwr\\Desktop\\11.conf"));
DatagramSocket socket = new DatagramSocket(9999);
byte[] content = new byte[2048];
DatagramPacket datagramPacket = new DatagramPacket(content,content.length);
while(true){//循环接受文件数据包
socket.receive(datagramPacket);
byte[] data= datagramPacket.getData();//获取数据报包中的数据
out.write(data, 0, datagramPacket.getLength());
boolean b = false;//判断是否接受完毕,具体逻辑未实现
if(b) {
//5.释放资源
out.close();
socket.close();
break;
}
}
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//发送方代码
private static void client() {
try {
InetAddress localHost = InetAddress.getLocalHost();
FileInputStream in = new FileInputStream(new File("C:\\Users\\lwr\\Desktop\\wrapper.conf"));
byte[] content = new byte[512];//建议设置为网络MTU,否则被分片
int i = 0;
//把读取的文件数据打包发送
DatagramSocket datagramSocket = new DatagramSocket();
DatagramPacket datagramPacket = new DatagramPacket(content, 0, localHost, 9999);
while ((i = in.read(content)) != -1) {
datagramPacket.setData(content, 0, i);
datagramSocket.send(datagramPacket);
}
datagramSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
发包捕获:
2、TCP
TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
原理:
-
三次握手建立连接
(我从本地的62644端口访问服务器80端口):
第一次:客户端发出连接请求SYN[Seq=随机数A]
第二次:服务器回应ACK[Ack=随机数A+1],并且加上自己的请求SYN[Seq=随机数B]
第三次:客户端回应ACK[Ack=随机数B+1],并且加上自己的请求SYN[Seq=随机数A+1]
TCP只有建立连接后才能传输数据 -
传输过程
TCP每发送一个数据[Seq=X],对方都要回应一个[Ack=X+1],如果没回应,就当作没接收到。 -
四次握手关闭连接
主要就是客户端向服务器说要关闭连接,服务器回应收到了请求;
服务器就绪后向客户端说可以关闭了,客户端回应收到(然后客户端等待2个MSL后关闭:RFC793中规定MSL为2分钟)。
搬个网络图:
Socket代码示例:
//tcp接受方:
private static void server() throws IOException {
ServerSocket serverSocket = new ServerSocket(8888);// 1024-65535的某个端口
Socket socket = serverSocket.accept();
// 3、获取输入流,并读取客户端信息
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String info = null;
while ((info = br.readLine()) != null) {
System.out.println("我是服务器,客户端说:" + info);
}
socket.shutdownInput();// 关闭输入流
// 4、获取输出流,响应客户端的请求
OutputStream os = socket.getOutputStream();
PrintWriter pw = new PrintWriter(os);
pw.write("我是服务器,已收到请求。");
pw.flush();
// 5、关闭资源
pw.close();
os.close();
br.close();
isr.close();
is.close();
socket.close();
serverSocket.close();
}
//tcp请求方:
public void client() throws Exception {// 客户端
// 1、创建客户端Socket,指定服务器地址和端口
Socket socket = new Socket("127.0.0.1", 8888);
// 2、获取输出流,向服务器端发送信息
OutputStream os = socket.getOutputStream();// 字节输出流
PrintWriter pw = new PrintWriter(os);// 将输出流包装成打印流
pw.write("我是客户端,我发送了请求。");
pw.flush();
socket.shutdownOutput();
// 3、获取输入流,并读取服务器端的响应信息
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String info = null;
while ((info = br.readLine()) != null) {
System.out.println("我是客户端,服务器说:" + info);
}
// 4、关闭资源
br.close();
is.close();
pw.close();
os.close();
socket.close();
}
包捕获: