2013-08-08 50 views
7

Tôi đang lưu trữ một trang web từ nhà. Tôi đã tạo máy chủ HTTP của riêng mình bằng cách sử dụng Java. Đây là một SSCCE:Máy chủ Java HTTP không hoạt động

if(command.startsWith("GET")) 
{ 
      //client is a socket on which I reply. 
      PrintWriter pw = new PrintWriter(client.getOutputStream(), true); 
    String commule = command.split(" "); 
    if(commule[0].equals("GET")) 
    { 
     if(commule[1].contains(".")) 
     { 
      File file = new File(GEQO_SERVER_ROOT + commule[1].substring(1).replaceAll("%20", " ")); 
      if(file.exists()) 
      { 
       OutputStream out = client.getOutputStream(); 
       InputStream stream = new FileInputStream(file); 

       String response = new String(); 
       response += "HTTP/1.1 200 OK\r\n"; 
       response += "Date: Thu, 08 Aug 2013 08:49:37 GMT\r\n"; 
       response += "Content-Type: text/html\r\n"; 
       response += "Content-Length: " + file.length() + "\r\n"; 
       response += "Connection: keep-alive\r\n"; 
       response += "\r\n"; 
       pw.write(response); //Assume I already initialized pw as a PrintWriter 
            pw.flush(); 
       copy(stream, out); 
       stream.close(); 
       out.close(); 
      } 
      else 
      { 
       pw.write("<html><h1>The request 404ed.</h1>"); 
       pw.write("<body>The requested URL <b>" + commule[1] + "</b> could not be found on this server.</body></html>"); 
            pw.flush(); 
      } 
     } 
     else 
     { 
      BufferedReader br = new BufferedReader(new FileReader(GEQO_SERVER_ROOT + commule[1].substring(1) + "main.html")); 
      String sCurrentLine; 
      while ((sCurrentLine = br.readLine()) != null) 
      { 
       pw.print(sCurrentLine); 
      } 
      br.close(); 
     } 
    } 
    else 
    { 
     pw.println("Unrecognized HTTP command."); 
    } 
} 

Đây là nguồn gốc main.html:

<html>
<title>Geqo Server</title>
<body>Geqo server online and functioning!</body>
</html>

Vấn đề là khi tôi cố gắng truy cập trang này bằng Chrome, nó hiển thị chính xác (Ít nhất là khi sử dụng 127.0.0.1). Nhưng khi tôi thử truy cập nó trên Firefox trên 127.0.0.1, nó hoạt động, nhưng chỉ cho tôi nguồn html. IE cũng chỉ cung cấp cho tôi nguồn. Bất cứ ai có thể cho tôi biết tại sao Firefox và IE chỉ hiển thị nguồn, thay vì phân tích nó?

Tôi nghĩ rằng đây có chứa một số manh mối (Firebug ảnh chụp màn hình):

Firebug screenshot

nguồn của tôi dường như được sắp tới trong một thẻ <pre>. Tôi donno tại sao, nhưng không phải là loại vấn đề?

Tôi chuyển tiếp cổng. Dưới đây là các trang của trang: http://110.172.170.83:17416/ (Xin lỗi, Stackoverflow không cho phép liên kết số.)

EDIT: Tôi đã tìm thấy sự cố. Nhưng trước khi tôi giải thích, nhờ có Bart cho SSCCE, mà tôi đã sử dụng để so sánh với mã của tôi. Đây là vấn đề: Tuyên bố if trên dòng thứ tám if(commule[1].contains(".")) làm cho mã bỏ qua hầu hết mã ở đây. Trong khối else tương ứng, thậm chí không có lệnh để gửi tiêu đề. Cảm ơn artbristol vì đã chỉ ra điều đó.

Xin cảm ơn trước.

+0

Có vẻ là tốt. Có thể là các tiêu đề không chính xác trên nền tảng hệ điều hành của bạn như đối với '\ r \ n' và Chrome đưa ra một số giả định. – PeterMmm

+0

Tôi không nghĩ vậy. Tôi đang sử dụng Windows 7 và hơn nữa, nó hoạt động trên Chrome. – Hele

+0

Sử dụng firebug trong Firefox, loại nội dung mà phản hồi có cho google.com là 'text/html; charset = UTF-8', hãy thử thêm bộ ký tự, chỉ để xem điều gì xảy ra – morgano

Trả lời

5

Trình viết chữ của bạn không bị xóa (như Ernest đã chỉ ra), vì vậy không có tiêu đề HTTP nào được gửi đi. Nhìn vào kết quả của việc kết nối trực tiếp - nó chỉ trả về dữ liệu thô, không có tiêu đề.

nc 110.172.170.83 17416 
GET/

<html><title>Geqo Server</title><body>Geqo server online and functioning!</body></html> 

Viết máy chủ HTTP là làm việc chăm chỉ. Trừ khi điều này là dành cho một bài tập, bạn nên sử dụng một bài tập có sẵn, chẳng hạn như Jetty, hoặc máy chủ Sun HTTP được cài sẵn trong JDK.

Chỉnh sửa - A PrintWriter thực sự không thích hợp để thực hiện HTTP. Nó được thiết kế để xử lý dữ liệu theo từng dòng như tệp được ghi vào đĩa. Nó cũng phụ thuộc vào cài đặt nền tảng cụ thể cho mã hóa văn bản và kết thúc dòng. Kiểm tra HTTP spec để biết thêm chi tiết về cách một máy chủ HTTP thích hợp phải hoạt động.

+0

Yea, nó chỉ là một bài tập. :) – Hele

+0

+1 thực sự, tôi đã thử nó quá. Tôi không tin bạn đã thêm lời gọi "tuôn ra" mà tôi đã đề xuất! –

+0

Kiểm tra mã được cập nhật. Tôi thêm tuôn ra.Nếu bạn cố gắng kết nối với IP của tôi ngay bây giờ, bạn có thể xem kết quả. Tôi đang đỏ mặt. – Hele

1

Dường như có một số vấn đề tiềm ẩn khi lưu vào bộ đệm. Bạn viết một số đầu ra của bạn vào một bao bọc PrintWriter xung quanh out và đầu ra khác trực tiếp đến out. Tôi chắc chắn sẽ thêm một cuộc gọi đến pw.flush() sau cuộc gọi pw.write().

+0

Chỉ cần thử điều đó. Nhưng vấn đề vẫn còn tồn tại. – Hele

0

Bạn không gửi bất kỳ tiêu đề phản hồi nào.

Tôi không tìm thấy định nghĩa của pw trong mã nguồn?

+0

Có một bình luận sau đó nói rằng nó được khởi tạo. Vui lòng kiểm tra câu hỏi. – Hele

+0

Lỗi của tôi. Tuy nhiên nó sẽ là tốt để xem cách PrintWriter được khởi tạo. –

+0

Tôi đã cập nhật câu hỏi của mình. Hãy kiểm tra. – Hele

1

Bạn kích hoạt autoFlush với đối số thứ hai để

new PrintWriter(client.getOutputStream(), true) 

http://docs.oracle.com/javase/7/docs/api/java/io/PrintWriter.html

Không giống như các lớp PrintStream, nếu tự động xả được kích hoạt nó sẽ được thực hiện chỉ khi một trong những println, printf, hoặc phương thức định dạng được gọi, thay vì bất cứ khi nào một ký tự dòng mới xảy ra là đầu ra. Những phương pháp này sử dụng khái niệm riêng của nền tảng của dấu tách dòng chứ không phải ký tự dòng mới.

Vì vậy, về cơ bản, pw.write() của bạn không tuôn ra luồng đầu ra. Vì vậy, tất cả các bạn cần phải làm là thay thế

pw.write(response); 

với

pw.println(response); 
+0

Chỉ cần thử điều đó - không hoạt động: ( – Hele

+1

Tôi đã tạo [thử nghiệm nhỏ] (http://pastebin.com/QjjvCqmx) càng gần càng tốt cho trường hợp của bạn (đơn giản). Mã này đã in ra HTML được bỏ ghim khi ' write' đã được gọi và phiên bản phân tích trên 'println'. Bạn đã thử thoát khỏi lệnh' copy() 'và chỉ cần in một chuỗi đơn giản? – Bart

+0

Mã của bạn dường như hoạt động, hmmmm ...., nhưng tôi vẫn làm ' nt Giữ, chạy thử nghiệm .. – Hele

Các vấn đề liên quan