简单的web服务器实现视频播放

准备写一个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这里很重要。
[java]  view plain  copy
  1. package duola;  
  2.   
  3. import java.io.IOException;  
  4. import java.net.ServerSocket;  
  5. import java.net.Socket;  
  6. import java.util.concurrent.ExecutorService;  
  7. import java.util.concurrent.Executors;  
  8.   
  9. /* 
  10.  * 1,多个浏览器同时访问(多线程) 
  11.  * 2.如何提供服务(socket) 
  12.  * 3,如何返回响应(IO) 
  13.  * 山寨web服务器 
  14.  */  
  15. public class TomDog {  
  16.       
  17.     private static int PORT = 8080;  
  18.       
  19.     public static void main(String[] args){  
  20.         /* 
  21.          * 通过命令行设置端口 
  22.          */  
  23.         int p = (args.length > 0)?Integer.parseInt(args[0]):PORT;  
  24.         new TomDog().start(p);  
  25.     }  
  26.       
  27.     /* 
  28.      * 服务启动方法 
  29.      * 创建socket服务器 
  30.      */  
  31.     public void start(int port){  
  32.         try{  
  33.             ServerSocket ss = new ServerSocket(port);  
  34.             System.out.println("----------------监听[" + port + "]端口的服务器启动----------------");  
  35.             while(true){  
  36.                 Socket socket = ss.accept();  
  37.                 System.out.println("-------------有客户端请求------------");  
  38.                 //new Thread(new HandlerRquestThread(socket));//线程的方法,效率一般  
  39.                 /* 
  40.                  * 创建向城池,将任务提交给线程池去处理 
  41.                  */  
  42.                 ExecutorService pool = Executors.newFixedThreadPool(100);//线程池,预计100个同时来  
  43.                 pool.submit(new HandlerRquestThread(socket));//有人来,就从池子里面取出一个线程  
  44.             }  
  45.         }catch(IOException e){  
  46.             e.printStackTrace();  
  47.         }  
  48.     }  
  49. }  

[java]  view plain  copy
  1. package duola;  
  2.   
  3. import java.io.BufferedInputStream;  
  4. import java.io.BufferedReader;  
  5. import java.io.File;  
  6. import java.io.FileInputStream;  
  7. import java.io.FileNotFoundException;  
  8. import java.io.IOException;  
  9. import java.io.InputStream;  
  10. import java.io.InputStreamReader;  
  11. import java.io.PrintStream;  
  12. import java.net.Socket;  
  13. import java.net.URLDecoder;  
  14.   
  15. /* 
  16.  * 专门处理不同的客户端请求的多线程类 
  17.  */  
  18. public class HandlerRquestThread implements Runnable{  
  19.     private InputStream in = null;  
  20.     //因为混色机浏览器内容的输出,所以使用了printStream 标准输出流  
  21.     private PrintStream out = null;  
  22.     public static final String WEB_ROOT = "H:"+File.separator+"AppServ"+File.separator+"www"+File.separator;  
  23.     public static final boolean DirShow = true;//是否允许列出目录文件  
  24.       
  25.     /* 
  26.      * 通过构造器获得Socket 
  27.      * 并通过Socket获取对客户端的输入和输出流 
  28.      */  
  29.     public HandlerRquestThread(Socket socket){  
  30.         try {  
  31.             in = socket.getInputStream();  
  32.             out = new PrintStream(socket.getOutputStream());  
  33.         } catch (IOException e) {  
  34.             // TODO Auto-generated catch block  
  35.             e.printStackTrace();  
  36.         }  
  37.     }  
  38.       
  39.     /* 
  40.      * 解析请求头,获得客户端请求的资源名称 
  41.      * in 输入流 
  42.      * return 请求的资源名称 
  43.      */  
  44.     public String parseRequestHead(InputStream in) throws IOException{  
  45.         //客户端发起请求会将一些请求数据包含在请求头中  
  46.         BufferedReader br = new BufferedReader(new InputStreamReader(in));  
  47.         //请求头的第一行将包含请求的方式,资源,协议  
  48.         String headContent = br.readLine();  
  49.         String[] heads = headContent.split(" ");//空格分割成数组  
  50.         System.out.println("解析请求头:");  
  51.         System.out.println(headContent);  
  52.         if(heads[1].equals("/"))  
  53.             heads[1] = heads[1]+"index.html";  
  54.         return heads[1];  
  55.     }  
  56.       
  57.       
  58.     public void getFile(String fileName) throws IOException{  
  59.         File file = new File(WEB_ROOT+fileName);  
  60.         System.out.println("发送文件:");  
  61.         System.out.println(file.toString());  
  62.         if(!file.exists()){  
  63.             //System.out.println("不存在");  
  64.             sendError("404""您请求的资源["+fileName+"]不存在!");  
  65.         }else if(file.isDirectory()){  
  66.             File temp = new File(WEB_ROOT+fileName+File.separator+"index.html");  
  67.             if(temp.exists()){  //首页存在,显示首页  
  68.                 getFile(fileName+File.separator+"index.html");  
  69.             }else if(DirShow){  
  70. //              if(fileName.endsWith("/")){  
  71. //              //如果文件不以/结尾,文件超链接不会以file为当前目录,而是结尾有/的,本来想用301重定向,后来用../file/搞定了  
  72. //                  Dirshow(file);  
  73. //              }  
  74.                 Dirshow(file);  
  75.             }else  
  76.                 sendError("403""403 Forbidden");  
  77.         }else{  
  78.             //FileInputStream fis = new FileInputStream(file);  
  79.             BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));  
  80.             byte[] buff = new byte[(int)file.length()];  
  81.             int len = bis.read(buff);  
  82.               
  83.             out.println("HTTP/1.1 200 OK");  
  84.             out.println();  
  85.             out.write(buff);  
  86.         }  
  87.         out.flush();  
  88.         out.close();  
  89.     }  
  90.       
  91.       
  92.     /* 
  93.      * 301重定向,请求头这样写就好了 
  94.      * "HTTP/1.1 301 Moved Permanently" ) ; 
  95.      *"Location: http://www.bloghuman.com" ); 
  96.      */  
  97.       
  98.     /* 
  99.      * 列出文件目录 
  100.      *  
  101.      */  
  102.     public void Dirshow(File file){  
  103.         //String[] filenames = file.list();  
  104.         File[] files = file.listFiles();  
  105.         StringBuilder sb = new StringBuilder("<html><head><title>"+file.getName()+"的索引</title>");  
  106.         sb.append("<meta http-equiv='Content-Type' content='text/html;charset=gbk'></head>");  
  107.         sb.append("<body>");  
  108.         sb.append("<center><h1><font color='green'>"+file.getName()+"的索引</font></h1></center>");  
  109.         sb.append("<hr color=red>");  
  110.           
  111.         sb.append("<img src=/images/folder.png style='width:20px;height:20px;'> ");  
  112.         sb.append("<a href=..><font size=4>返回上一级</font></a><br/>");  
  113.           
  114.         for (File f : files) {  
  115.             if(f.isDirectory()){  
  116.                 sb.append("<img src=/images/folder.png style='width:20px;height:20px;'> ");  
  117.                 sb.append("<a href=../"+file.getName()+"/"+f.getName()+"><font size=4>"+f.getName()+"/</font></a><br/>");  
  118.             }else{  
  119.                 sb.append("<img src=/images/file.png style='width:20px;height:20px;'> ");  
  120.                 sb.append("<a href=../"+file.getName()+"/"+f.getName()+"><font size=4>"+f.getName()+"</font></a><br/>");  
  121.             }  
  122.         }  
  123.           
  124.         sb.append("</body></html>");  
  125.         out.println("HTTP/1.1 200 OK");  
  126.         out.println();  
  127.         out.print(sb.toString());  
  128.     }  
  129.       
  130.     /* 
  131.      * 输出错误信息 
  132.      * 编号,信息 
  133.      */  
  134.     public void sendError(String errorNumber, String errorMsg){  
  135.         StringBuilder sb = new StringBuilder("<html><head><title>错误页面</title>");  
  136.           
  137.         sb.append("<meta http-equiv='Content-Type' content='text/html;charset=gbk'></head>");  
  138.         sb.append("<body>");  
  139.         sb.append("<center><h1><font color='green'>"+errorNumber+"</font></h1></center>");  
  140.         sb.append("<hr color=red>");  
  141.         sb.append("<p>"+errorMsg+"</p>");  
  142.         sb.append("<img src=/images/error.jpg>");  
  143.         sb.append("</body></html>");  
  144.         out.println("HTTP/1.1 404 Not Found");  
  145.         out.println();  
  146.         out.print(sb.toString());  
  147. //      out.flush();  
  148. //      out.close();//后面处理函数那里有清空和关闭  
  149.     }  
  150.       
  151.     @SuppressWarnings("deprecation")  
  152.     public void run(){  
  153.         System.out.println("------------开始处理用户请求------------");  
  154.         try {  
  155.             String fileName = parseRequestHead(this.in);  
  156.             fileName = URLDecoder.decode(fileName, "utf-8");//url解码,中文目录文件的需要  
  157.             getFile(fileName);  
  158.         } catch (IOException e) {  
  159.             // TODO Auto-generated catch block  
  160.             e.printStackTrace();  
  161.         }  
  162.     }  
  163. }  

猜你喜欢

转载自blog.csdn.net/qq_34468186/article/details/80046878