Java.net实现视频渐进式播放(原创禁止转载)

我设置了三个类:

第一个类:用于接受客户端请求

package com.dm.server;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Base64;

public class PC_Server {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		ServerSocket serverSocket = new ServerSocket(8888);
		while(true){
			Socket socket = serverSocket.accept();//接受客户端请求
			new SocketVideoThread(socket).start();
		}
	}
	
}

第二个类:用于读取客户端请求的头信息

package com.dm.server;

import java.io.InputStream;
import java.util.ArrayList;

public class SocketUtil {
	/*
	 * 取得socket头信息,也就是客户端请求的头信息
	 */
	public static String readLine(InputStream is, int total) {
		try{
			ArrayList lineByteList = new ArrayList();
			byte bt;
			int index = 0;
			if(total == 0){
				do{
					bt = (byte) is.read();
					lineByteList.add(bt);
				}while(bt != 10 && bt != -1);
			}else{
				do{
					bt = (byte) is.read();
					lineByteList.add(bt);
					total --;
				}while(total > 0);
				
			}
			byte[] lineByteArr = new byte[lineByteList.size()];
			for(int i=0;i < lineByteArr.length; i++){
				lineByteArr[i] = (byte) lineByteList.get(i);
			}
			lineByteList.clear();
			String str = new String(lineByteArr,"GBK");
			if (str.startsWith("Referer")) {//如果有Referer头时,使用UTF-8编码   
				str = new String(lineByteArr, "UTF-8");   
			}   
			return str;
		}catch(Exception e){
			e.printStackTrace();
		}
		return null;
	}
}

第三个类:用于将视频数据发送到客户端

package com.dm.server;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.RandomAccessFile;
import java.net.Socket;
import java.nio.file.Files;
import java.nio.file.Paths;

public class SocketVideoThread extends Thread {
	private Socket socket = null;
	
	public SocketVideoThread(Socket socket){
		this.socket = socket;
	}
	
	public void run(){
		try {

			RandomAccessFile rf = new RandomAccessFile("F:\\星球大战9:天行者崛起.BD1280高清中英双字版.mp4", "r");//对视频数据只读
			InputStream is = socket.getInputStream();//取得向客户端到输出流
			int range = 0;//视频数据读取的起始位置
			String aaa;//客户端请求的头信息
			do{
				aaa = SocketUtil.readLine(is, 0);//取得客户端请求到头信息,可打印aaa得头信息
				if(aaa.indexOf("Range") != -1){
					range = Integer.parseInt(aaa.split("=")[1].split("-")[0]);//取得视频读取的起始位置
				}
				System.out.println(aaa);
			}while(!aaa.equals("\r\n"));//将头文件读完,这里有时候头信息读完后一直循环,一直没找到原因,本代码里面也没有解决
			
			
			PrintStream ps = new PrintStream(this.socket.getOutputStream());
			ps.println("HTTP/1.1 206");//206表示返回部分内容,本篇博客代码只能用H5的video标签播放,不能支持下载,我想是因为头信息的原因,有时间我再发关于下载的
			ps.println("Access-Control-Allow-Origin:*");//允许跨域请求
			ps.println("Content-Length:"+(rf.length() - range));//接收到数据长度
			ps.println("Content-Range:bytes "+range+"-"+(rf.length()-1)+"/"+rf.length());//格式为 bytes [要下载的开始位置]-[结束位置]/[文件总大小]
			ps.println("content-type:application/octet-stream");//告诉客户端输出的数据类型
			ps.println();//告诉客户端头信息发送完毕,下面发送视频数据
			
			do{//循环发送,每次发送为10兆可以自己修改,如一次性发送完对小视频还可以,对几个G内存的视频就会出现内存溢出错误
				rf.seek(range);//移动指针从range开始读取视频
				byte[] b = new byte[10485760];//定义一个10兆的字节数组
				rf.read(b);//读取10兆的视频数据
				ps.write(b);//将数据发送到客户端
				ps.flush();//缓冲、发送
				if(range + 10485760 >= rf.length()-1){//直到读完,发送完毕
					rf.seek(range);//移动指针从range开始读取
					byte[] c = new byte[(int) (rf.length() - range)];
					rf.read(c);
					ps.write(c);
					ps.flush();
					break;
				}
				range += 10485760;
			}while(true);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

结果:完美播放

Java.net实现视频渐进式播放(原创禁止转载)_第1张图片

你可能感兴趣的:(Java.net,java,.net)