用java写简单的web服务器,在宿舍提供视频播放

5 篇文章 0 订阅

准备写一个web服务器专门供宿舍看电影用。
之前已经实现基本的web服务器,今天又把视频播放器弄好了,接下来就是整合了。
视频播放器,用的CuPlayer,改改demo就行,之前不成功可能是没在localhost下测试,视频是需要服务器提供文件传输服务的。
1.网页flash播放器原理:我猜的哈
目前流行播放视频用swf,让后用swf去加载视频。swf本身可以播放视频(类似qq影音的本地视频播放工具),放到网页上,然后播放线上的视频,这时把线上的看成“本地的”了,原理还是那一套,可以有进度。
我喜欢CKplayer,这个很方便自己定义,换换图片,即可,代码可读性高,

2,TomDog 山寨web服务器
根据51cto上面讲得来做,很不错,老师讲得很细致,原来以为很难得东西分分钟就搞定了,思路很清晰,代码运用很熟练。我在他的基础上做了一点点完善。

web服务器我的理解就是部署在网站服务器上,与浏览器交互的一组程序,最近学习了一下51job上的一个视频,仿照tomcat写的一个简单的web服务器。

先来罗列一下用java写web服务器需要的知识点。

1,服务器与客户端通信,socket。其中服务器端是serversocket

2,服务器需要同时处理多个浏览器的请求,所以需要用到多线程
3,如何相应请求,io操作
4,一些web基础,请求头,html等

下面介绍下代码:
TomDog类:
     main()函数,参数可指定端口号,启动start。
     start函数,启动对应端口号,监听socket请求,创建线程池处理

HandlerRquestThread类: 实现runnable接口(线程)定义网站根目录。
     构造函数,拿到socket,处理得到输入和输出流in/out
     paresRequestHead(),处理请求头,获得请求文件,并返回
     getFile,打印目标文件,即找到相应文件转向输出流
     Dirshow,用于罗列目录,可以404禁止
     sendError(),发送错误信息
     run(),线程函数题,调用上面函数拿到文件命,并把文件输出到输出流。

难点是需要基础足够扎实,线程,io这里很重要。
package duola;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/*
 * 1,多个浏览器同时访问(多线程)
 * 2.如何提供服务(socket)
 * 3,如何返回响应(IO)
 * 山寨web服务器
 */
public class TomDog {
	
	private static int PORT = 8080;
	
	public static void main(String[] args){
		/*
		 * 通过命令行设置端口
		 */
		int p = (args.length > 0)?Integer.parseInt(args[0]):PORT;
		new TomDog().start(p);
	}
	
	/*
	 * 服务启动方法
	 * 创建socket服务器
	 */
	public void start(int port){
		try{
			ServerSocket ss = new ServerSocket(port);
			System.out.println("----------------监听[" + port + "]端口的服务器启动----------------");
			while(true){
				Socket socket = ss.accept();
				System.out.println("-------------有客户端请求------------");
				//new Thread(new HandlerRquestThread(socket));//线程的方法,效率一般
				/*
				 * 创建向城池,将任务提交给线程池去处理
				 */
				ExecutorService pool = Executors.newFixedThreadPool(100);//线程池,预计100个同时来
				pool.submit(new HandlerRquestThread(socket));//有人来,就从池子里面取出一个线程
			}
		}catch(IOException e){
			e.printStackTrace();
		}
	}
}

package duola;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.URLDecoder;

/*
 * 专门处理不同的客户端请求的多线程类
 */
public class HandlerRquestThread implements Runnable{
	private InputStream in = null;
	//因为混色机浏览器内容的输出,所以使用了printStream 标准输出流
	private PrintStream out = null;
	public static final String WEB_ROOT = "H:"+File.separator+"AppServ"+File.separator+"www"+File.separator;
	public static final boolean DirShow = true;//是否允许列出目录文件
	
	/*
	 * 通过构造器获得Socket
	 * 并通过Socket获取对客户端的输入和输出流
	 */
	public HandlerRquestThread(Socket socket){
		try {
			in = socket.getInputStream();
			out = new PrintStream(socket.getOutputStream());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/*
	 * 解析请求头,获得客户端请求的资源名称
	 * in 输入流
	 * return 请求的资源名称
	 */
	public String parseRequestHead(InputStream in) throws IOException{
		//客户端发起请求会将一些请求数据包含在请求头中
		BufferedReader br = new BufferedReader(new InputStreamReader(in));
		//请求头的第一行将包含请求的方式,资源,协议
		String headContent = br.readLine();
		String[] heads = headContent.split(" ");//空格分割成数组
		System.out.println("解析请求头:");
		System.out.println(headContent);
		if(heads[1].equals("/"))
			heads[1] = heads[1]+"index.html";
		return heads[1];
	}
	
	
	public void getFile(String fileName) throws IOException{
		File file = new File(WEB_ROOT+fileName);
		System.out.println("发送文件:");
		System.out.println(file.toString());
		if(!file.exists()){
			//System.out.println("不存在");
			sendError("404", "您请求的资源["+fileName+"]不存在!");
		}else if(file.isDirectory()){
			File temp = new File(WEB_ROOT+fileName+File.separator+"index.html");
			if(temp.exists()){	//首页存在,显示首页
				getFile(fileName+File.separator+"index.html");
			}else if(DirShow){
//				if(fileName.endsWith("/")){
//				//如果文件不以/结尾,文件超链接不会以file为当前目录,而是结尾有/的,本来想用301重定向,后来用../file/搞定了
//					Dirshow(file);
//				}
				Dirshow(file);
			}else
				sendError("403", "403 Forbidden");
		}else{
			//FileInputStream fis = new FileInputStream(file);
			BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
			byte[] buff = new byte[(int)file.length()];
			int len = bis.read(buff);
			
			out.println("HTTP/1.1 200 OK");
			out.println();
			out.write(buff);
		}
		out.flush();
		out.close();
	}
	
	
	/*
	 * 301重定向,请求头这样写就好了
	 * "HTTP/1.1 301 Moved Permanently" ) ;
  	 *"Location: http://www.bloghuman.com" );
	 */
	
	/*
	 * 列出文件目录
	 * 
	 */
	public void Dirshow(File file){
		//String[] filenames = file.list();
		File[] files = file.listFiles();
		StringBuilder sb = new StringBuilder("<html><head><title>"+file.getName()+"的索引</title>");
		sb.append("<meta http-equiv='Content-Type' content='text/html;charset=gbk'></head>");
		sb.append("<body>");
		sb.append("<center><h1><font color='green'>"+file.getName()+"的索引</font></h1></center>");
		sb.append("<hr color=red>");
		
		sb.append("<img src=/images/folder.png style='width:20px;height:20px;'> ");
		sb.append("<a href=..><font size=4>返回上一级</font></a><br/>");
		
		for (File f : files) {
			if(f.isDirectory()){
				sb.append("<img src=/images/folder.png style='width:20px;height:20px;'> ");
				sb.append("<a href=../"+file.getName()+"/"+f.getName()+"><font size=4>"+f.getName()+"/</font></a><br/>");
			}else{
				sb.append("<img src=/images/file.png style='width:20px;height:20px;'> ");
				sb.append("<a href=../"+file.getName()+"/"+f.getName()+"><font size=4>"+f.getName()+"</font></a><br/>");
			}
		}
		
		sb.append("</body></html>");
		out.println("HTTP/1.1 200 OK");
		out.println();
		out.print(sb.toString());
	}
	
	/*
	 * 输出错误信息
	 * 编号,信息
	 */
	public void sendError(String errorNumber, String errorMsg){
		StringBuilder sb = new StringBuilder("<html><head><title>错误页面</title>");
		
		sb.append("<meta http-equiv='Content-Type' content='text/html;charset=gbk'></head>");
		sb.append("<body>");
		sb.append("<center><h1><font color='green'>"+errorNumber+"</font></h1></center>");
		sb.append("<hr color=red>");
		sb.append("<p>"+errorMsg+"</p>");
		sb.append("<img src=/images/error.jpg>");
		sb.append("</body></html>");
		out.println("HTTP/1.1 404 Not Found");
		out.println();
		out.print(sb.toString());
//		out.flush();
//		out.close();//后面处理函数那里有清空和关闭
	}
	
	@SuppressWarnings("deprecation")
	public void run(){
		System.out.println("------------开始处理用户请求------------");
		try {
			String fileName = parseRequestHead(this.in);
			fileName = URLDecoder.decode(fileName, "utf-8");//url解码,中文目录文件的需要
			getFile(fileName);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}


     


  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值