2012-12-11 142 views
0

我正在嘗試一個簡單的java代碼http, 如果我使用chrome與文件位置(http:// localhost:8888/somefile.mp3) 它工作正常,但如果我在iPhone上使用safari,它拋出錯誤: java.net.SocketException:損壞的管道 但如果我使用LAMP或任何PHP服務器,它工作正常。 我怎樣才能使它與Java一起工作呢?如何使用java作爲服務器流式傳輸音樂?

這是HTTP服務器:

package com.streamternet; 


import java.io.BufferedReader; 
import java.io.DataOutputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.InputStreamReader; 
import java.net.InetAddress; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.net.URLDecoder; 
import java.util.StringTokenizer; 

public class HTTPServer extends Thread { 

static final String HTML_START = 
     "<html>" + 
       "<title>HTTP Server in java</title>" + 
       "<body>"; 

static final String HTML_END = 
     "</body>" + 
       "</html>"; 

Socket connectedClient = null; 
BufferedReader inFromClient = null; 
DataOutputStream outToClient = null; 


public HTTPServer(Socket client) { 
    connectedClient = client; 
} 

public void run() { 

    try { 

     System.out.println("The Client "+ 
       connectedClient.getInetAddress() + ":" + connectedClient.getPort() + " is connected"); 

     inFromClient = new BufferedReader(new InputStreamReader (connectedClient.getInputStream())); 
     outToClient = new DataOutputStream(connectedClient.getOutputStream()); 

     String requestString = inFromClient.readLine(); 
     String headerLine = requestString; 

     StringTokenizer tokenizer = new StringTokenizer(headerLine); 
     String httpMethod = tokenizer.nextToken(); 
     String httpQueryString = tokenizer.nextToken(); 

     StringBuffer responseBuffer = new StringBuffer(); 
     responseBuffer.append("<b> This is the HTTP Server Home Page.... </b><BR>"); 
     responseBuffer.append("The HTTP Client request is ....<BR>"); 

     System.out.println("The HTTP request string is ...."); 
     while (inFromClient.ready()) 
     { 
      // Read the HTTP complete HTTP Query 
      responseBuffer.append(requestString + "<BR>"); 
      System.out.println(requestString); 
      requestString = inFromClient.readLine(); 
     } 

     if (httpMethod.equals("GET")) { 
      if (httpQueryString.equals("/")) { 
       // The default home page 
       sendResponse(200, responseBuffer.toString(), false); 
      } else { 
       //This is interpreted as a file name 
       String fileName = httpQueryString.replaceFirst("/", ""); 
       fileName = URLDecoder.decode(fileName); 
       fileName="/"+fileName; 
       if (new File(fileName).isFile()){ 
        sendResponse(200, fileName, true); 
       } 
       else { 
        sendResponse(404, "<b>The Requested resource not found ....</b>", false); 
       } 
      } 
     } 
     else sendResponse(404, "<b>The Requested resource not found ...." + 
       "Usage: http://127.0.0.1:5000 or http://127.0.0.1:5000/</b>", false); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

public void sendResponse (int statusCode, String responseString, boolean isFile) throws Exception { 

    String statusLine = null; 
    String serverdetails = "Server: Java HTTPServer"; 
    String contentLengthLine = null; 
    String fileName = null; 
    String contentTypeLine = "Content-Type: text/html" + "\r\n"; 
    FileInputStream fin = null; 

    if (statusCode == 200) 
     statusLine = "HTTP/1.1 200 OK" + "\r\n"; 
    else 
     statusLine = "HTTP/1.1 404 Not Found" + "\r\n"; 

    if (isFile) { 
     fileName = responseString; 
     fin = new FileInputStream(fileName); 
     contentLengthLine = "Content-Length: " + Integer.toString(fin.available()) + "\r\n"; 
     if (!fileName.endsWith(".htm") && !fileName.endsWith(".html")) 
      contentTypeLine = "Content-Type: audio/mpeg\r\n"; 
    } 
    else { 
     responseString = HTTPServer.HTML_START + responseString + HTTPServer.HTML_END; 
     contentLengthLine = "Content-Length: " + responseString.length() + "\r\n"; 
    } 

    outToClient.writeBytes(statusLine); 
    outToClient.writeBytes(serverdetails); 
    outToClient.writeBytes(contentTypeLine); 
    outToClient.writeBytes(contentLengthLine); 
    outToClient.writeBytes("Connection: close\r\n"); 
    outToClient.writeBytes("\r\n"); 

    if (isFile) 
     sendFile(fin, outToClient); 
    else 
     outToClient.writeBytes(responseString); 

    outToClient.close(); 
} 

public void sendFile (FileInputStream fin, DataOutputStream out) throws Exception { 
    byte[] buffer = new byte[1024] ; 
    int bytesRead; 

    while ((bytesRead = fin.read(buffer)) != -1) { 
     out.write(buffer, 0, bytesRead); 
     out.flush(); 
    } 
    fin.close(); 
} 

public static void main (String args[]) throws Exception { 

    ServerSocket Server = new ServerSocket (8888); 

    System.out.println ("TCPServer Waiting for client on port 8888"); 

    while(true) { 
     Socket connected = Server.accept(); 
     (new HTTPServer(connected)).start(); 
    } 
} 

}

回答

2

首先,這不是,這只是一個普通的HTTP請求 - 響應對話。縱觀你的服務器,它似乎以多種方式破裂,甚至很難說出Chrome爲什麼要下載任何東西。

我把minimal HTTP server online,只是爲了好玩。它遠非完整,它不可配置,並且只支持GET請求,但是如果您不想依賴於另一臺服務器或框架,我認爲這是一個很好的起點。它只能給出兩種響應:200 OK404 NOT FOUND。資源在CLASSPATH上搜索,並根據擴展名與MIME類型信息一起發送到客戶端。您可能需要添加MP3 MIME,但請注意,這只是一個玩具,僅用於展示HTTP的基礎知識。

代碼:

public class TinyHTTPServer { 

    public static void main(String[] args) throws IOException { 

     ServerSocket server = new ServerSocket(8888); 

     while (true) { 
      final Socket connection = server.accept(); 
      new Thread(new Runnable(){ 
       public void run() { 
        RequestHandler handler = new RequestHandler(); 
        handler.handle(connection); 
       } 
      }).start(); 
     } 
    } 

    public static class RequestHandler { 

     public void handle(Socket socket) { 
      try { 
       Scanner scanner = new Scanner(socket.getInputStream(), "US-ASCII"); 
       String path = getPath(scanner.nextLine()); 

       Response response = find(path); 

       PrintStream out = new PrintStream(socket.getOutputStream()); 

       for (String header : response.headers) { 
        out.print(header); 
        out.print("\r\n"); 
       } 

       out.print("\r\n"); 
       if (response.url != null) 
        writeEntity(response.url.openStream(), socket.getOutputStream()); 
       out.print("\r\n"); 

       out.flush(); 
      } catch (Exception exception) { 
       exception.printStackTrace(); 
      } finally { 
       try { 
        socket.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 

     private String getPath(String requestLine) throws IOException { 
      Matcher matcher = Pattern.compile("GET (/\\S*) HTTP/1\\.1").matcher(requestLine); 
      matcher.find(); 
      return matcher.group(1); 
     } 

     private Response find(String path) { 

      if (path.equals("/")) 
       path = "/index.html"; 

      Response response = new Response(); 
      URL url = RequestHandler.class.getResource(path); 

      if (url == null) { 
       response.headers.add("HTTP/1.1 404 NOT FOUND"); 
      } else { 
       response.url = url; 
       response.headers.add("HTTP/1.1 200 OK"); 

       String type = "application/octet-stream"; 
       String extension = url.toString(); 

       if (extension.endsWith(".mp3")) 
        type = "audio/mp3"; 
       else if (extension.endsWith(".html")) 
        type = "text/html; charset=utf-8"; 

       response.headers.add("Content-Type: " + type); 
      } 

      return response; 
     } 

     private void writeEntity(InputStream in, OutputStream out) throws IOException { 
      byte[] buffer = new byte[1024]; 
      int read = -1; 

      while ((read = in.read(buffer, 0, buffer.length)) > -1) { 
       out.write(buffer, 0, read); 
      } 
     } 

    } 

    public static class Response { 

     public List<String> headers = new LinkedList<String>(); 
     public URL url; 

    } 
} 
+0

非常感謝!這實際上解決了問題,現在它在iphone上播放。但我不能前進/回到這個播放,有沒有辦法改進這臺服務器,所以它會支持它? (它在燈上工作) – Dima

+0

這裏沒有HTTP是問題。如果您需要流媒體協議,請查看Adobe RTMP。但是,一旦文件完全下載,你肯定可以播放,暫停,跳過和快進,但這一切發生在客戶端 – Raffaele

+0

,爲什麼它可以在任何PHP服務器上工作? – Dima

1

不一致的行爲可能是由不同的瀏覽器發送微妙的不同HTTP請求,或者甚至可能嘗試使用功能,它是快速和骯髒的服務器造成的不支持。如果您的意圖僅僅是通過HTTP流式傳輸文件,那麼將極力鼓勵您嵌入一個小型的預構建Java HTTP守護進程,如jetty。

+0

,但我需要這個服務器是一個獨立的,有沒有它的任何解決方案? – Dima

+0

@DimaGoltsman這是什麼意思*這臺服務器必須是獨立的*?所有的HTTP服務器是獨立的 – Raffaele

+0

我的意思是說,我需要一個服務器,將運行一個主要的方法,而不是在tomcat或類似的 – Dima

相關問題