计网 | HTTP协议分段存取改造(附源码和运行效果)
Posted 米莱虾
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计网 | HTTP协议分段存取改造(附源码和运行效果)相关的知识,希望对你有一定的参考价值。
应用场景
在一些情况下,大型文件会连续性或周期性地追加内容,例如实时音频或视频源、区块链数据库和日志文件等。例如,HTTP客户机能够通过下载服务器上从开始到目前的整个文件来获取追加的内容。但是,这显然这对于网络来说是非常低效的。大部分情况下客户都按只需要最近追加的内容。又例如,客户机可以通过发送定期的、开放的字节范围来访问附加内容使用最后一个已知的结束字节位置作为范围开始的请求。现在需要在HTTP的基础上增加访问文件的范围信息,以便服务器可以只传输客户端需要的部分。考虑实现以下功能:
(1)Client可以正常请求Server上的整个文件。
(2)Client可以请求Server上某文件的某个范围。
(3)Server根据请求给出响应。
(4)请求范围的单位可设置。
(5)尽可能和原有HTTP兼容。
(6)如有可能,考虑不同server间的负载均衡。
源代码
客户端
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.Socket;
public class Client01
public static void main(String[] args)
JFrame frame = new JFrame();
frame.setBounds(500,300,800,600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel01 = new JPanel();
JPanel panel02 = new JPanel();
JPanel panel03 = new JPanel();
JPanel panel04 = new JPanel();
JPanel panel05 = new JPanel();
JPanel panel06 = new JPanel();
panel01.setBackground(Color.white);
panel02.setBackground(Color.white);
panel03.setBackground(Color.white);
panel04.setBackground(Color.white);
panel05.setBackground(Color.white);
panel06.setBackground(Color.white);
JLabel label01 = new JLabel("请输入ip地址:");
JLabel label02 = new JLabel("请输入port:");
JLabel label03 = new JLabel("请输入请求方式");
JLabel label04 = new JLabel("从字节");
JLabel label05 = new JLabel("到字节");
JTextField textField01 = new JTextField(12);
textField01.setFont(new Font("黑体",Font.BOLD,18));
JTextField textField02 = new JTextField(12);
textField02.setFont(new Font("黑体",Font.BOLD,18));
JTextField textField03 = new JTextField(12);
textField03.setFont(new Font("黑体",Font.BOLD,18));
JTextArea textArea = new JTextArea(30,30);
textArea.setFont(new Font("黑体",Font.BOLD,18));
JTextField textField04 = new JTextField(5);
textField04.setFont(new Font("黑体",Font.BOLD,18));
JTextField textField05 = new JTextField(5);
textField05.setFont(new Font("黑体",Font.BOLD,18));
JButton button = new JButton("连接");
button.setSize(10,20);
button.addActionListener(new ActionListener()
@Override
public void actionPerformed(ActionEvent e)
String path = textField03.getText();
if ("GET".equals(path))
try
int port = Integer.parseInt(textField02.getText());
//建立套接字socket
Socket socket = new Socket(textField01.getText(),port);
//通过套接字获取网络输出流OutputStream
OutputStream os = socket.getOutputStream();
//构建请求报文
StringBuilder stringBuilder = new StringBuilder();
//请求报文头
stringBuilder.append("GET /G:/jpg/2.txt HTTP/1.1\\r\\n");
stringBuilder.append("Host: hacker.jp\\r\\n");
stringBuilder.append("Connection: alive\\r\\n");
stringBuilder.append("Context-Type: text/plain\\r\\n");
stringBuilder.append("Context-Length: \\r\\n");
stringBuilder.append("\\r\\n");
stringBuilder.append("end\\r\\n");
//通过网络输出流输出到服务器
os.write(stringBuilder.toString().getBytes());
InputStream is = socket.getInputStream();
BufferedReader bf = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = bf.readLine())!=null)
textArea.append(line+"\\n");
socket.close();
catch (IOException e1)
e1.printStackTrace();
else if ("GETPART".equals(path))
int port = Integer.parseInt(textField02.getText());
try
Socket socket = new Socket(textField01.getText(),port);
OutputStream os = socket.getOutputStream();
//构建请求报文
StringBuilder stringBuilder = new StringBuilder();
//请求报文头
stringBuilder.append("GETPART /G:/jpg/2.txt HTTP/1.1\\r\\n");
stringBuilder.append("Host: hacker.jp\\r\\n");
stringBuilder.append("Connection: alive\\r\\n");
stringBuilder.append("Context-Type: text/plain\\r\\n");
stringBuilder.append("Context-Length: 10\\r\\n");
stringBuilder.append("\\r\\n");
//stringBuilder.append("unit: "+textField04.getText()+"$"+textField05.getText()+"7\\r\\n");
//stringBuilder.append("unit: 1$15\\r\\n");
stringBuilder.append("unit: ").append(textField04.getText()).append("$").append(textField05.getText()).append("\\r\\n");
//通过网络输出流输出到服务器
os.write(stringBuilder.toString().getBytes());
InputStream is = socket.getInputStream();
byte[] b = new byte[100];
int len = 0;
while ((len = is.read(b))!=-1)
textArea.append(new String(b,0,len));
socket.close();
catch (Exception e2)
e2.printStackTrace();
);
panel01.add(label01);
panel01.add(textField01);
panel02.add(label02);
panel02.add(textField02);
panel04.add(button);
panel03.add(textArea);
panel05.add(label03);
panel05.add(textField03);
panel06.add(label04);
panel06.add(textField04);
panel06.add(label05);
panel06.add(textField05);
frame.add(panel01);
frame.add(panel02);
frame.add(panel05);
frame.add(panel06);
frame.add(panel04);
frame.add(panel03);
frame.setVisible(true);
frame.setLayout(new GridLayout(6,1));
服务器
import java.io.*;
import java.lang.reflect.Array;
import java.net.ServerSocket;
import java.net.Socket;
public class Server
public static void main(String[] args)
try
//创建服务器端套接字
ServerSocket server = new ServerSocket(80);
//服务器进入等待状态等待客户端访问
Socket socket = server.accept();
//通过套接字获取输入流
InputStream is = socket.getInputStream();
//通过字节缓冲数组读出请求报文
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = br.readLine();
String str1 = line;
String[] arr = str1.split(" ");
String path = arr[1].substring(1);
if ("GET".equals(arr[0]))
while (line != null && !"".equals(line))
System.out.println(line);
line = br.readLine();
String[] arr1 = path.split("/");
StringBuffer sb = new StringBuffer();
sb.append(arr1[0]);
sb.append("\\\\");
sb.append(arr1[1]);
sb.append("\\\\");
sb.append(arr1[2]);
FileInputStream fos = new FileInputStream(sb.toString());
OutputStream os = socket.getOutputStream();
byte[] b = new byte[1024];
int len = 0;
while ((len = fos.read(b))!= -1)
os.write(b,0,len);
fos.close();
socket.close();
server.close();
else if("GETPART".equals(arr[0]))
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
String s = br.readLine();
System.out.println(s);
String[] arr2 = s.split(" ");
String[] arr3 = arr2[1].split("\\\\$");
int a1 = Integer.parseInt(arr3[0]);
int a2 = Integer.parseInt(arr3[1]);
String[] arr1 = path.split("/");
StringBuffer sb = new StringBuffer();
sb.append(arr1[0]);
sb.append("\\\\");
sb.append(arr1[1]);
sb.append("\\\\");
sb.append(arr1[2]);
FileInputStream fos = new FileInputStream(sb.toString());
OutputStream os = socket.getOutputStream();
int len = a1+a2;
byte[] b = new byte[200];
byte[] a = new byte[a2-a1];
while ((len = fos.read(b))!= -1)
a = subBytes(b,a1,a2);
os.write(a,0,a.length);
break;
br.close();
socket.close();
server.close();
catch (Exception e)
e.printStackTrace();
public static byte[] subBytes(byte[] src, int begin, int count)
byte[] bs = new byte[count];
for (int i=begin; i<begin+count; i++)
bs[i-begin] = src[i];
return bs;
运行效果
运行初始界面
发起GET(请求全部信息)界面
GET请求wireshark抓包图
发起GETPART(请求部分信息)界面
GET请求wireshark抓包图
以上是关于计网 | HTTP协议分段存取改造(附源码和运行效果)的主要内容,如果未能解决你的问题,请参考以下文章
半小时实现Java手撸Http协议,爽!!(附完整源码,建议收藏)