gpt4 book ai didi

java - BufferReader 卡在 readline() 中

转载 作者:行者123 更新时间:2023-12-02 01:50:30 24 4
gpt4 key购买 nike

我正在制作一个 HTTP 服务器和 HTTP Web 客户端,用于简单的 Http 请求和响应。

这是服务器的代码

import java.io.*;
import java.net.*;
import java.util.*;

public final class WebServer{

public static void main(String[] args) throws Exception{
//storing port number
int port = 2048;

//open socket and wait for TCP connection

ServerSocket serverConnect = new ServerSocket(port);
System.out.println("Server started.\nListening for connections on port : " + port + " ...\n");

// we listen until user halts server execution
while (true) {
//Construct an object to process the HTTP request message.
//This will call another class where we do everything else
HttpRequest request = new HttpRequest(serverConnect.accept());

//create a new thread to process the request
Thread thread = new Thread(request);
thread.start();

} //end of while

}//end of main
}//end of the class webServer

HttpRequest类的代码如下:

import java.io.*;
import java.net.*;
import java.util.*;

final class HttpRequest implements Runnable{

final static String CRLF = "\r\n";
Socket socket;

//start of constructor
public HttpRequest(Socket socket) throws Exception{

this.socket=socket;
}//end of constructor

//Implement the run() method of the Runnable interface.
public void run(){

try{
processRequest();
}
catch(Exception e){
System.out.println(e);
}
}//end of run

private void processRequest() throws Exception{

//Get a reference to the scoket's input and output streams.
InputStream is = socket.getInputStream();
DataOutputStream os = new DataOutputStream(socket.getOutputStream());

//set up the stream filters
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//Get the request line of the HTTP request message.
String requestLine = br.readLine();

//Display the request line
System.out.println();
System.out.println(requestLine);

//Get and display the header lines.

String headerLine = null;
while((headerLine = br.readLine()).length()!=0){
System.out.println(headerLine);
}
//System.out.println(requestLine);

//Extract the filename from the request line.
StringTokenizer tokens = new StringTokenizer(requestLine);
tokens.nextToken(); //skip over the method, which should be. "GET"
String fileName = tokens.nextToken();

//Prepend a "." so that file request is within the current directory
fileName = "." + fileName;
//printing for test
//System.out.println(fileName);

//Open the requested file
FileInputStream fis = null;
boolean fileExists = true;
try{
fis = new FileInputStream(fileName);
}
catch(FileNotFoundException e){
fileExists = false;
}

//Construct the response message
String statusLine = null;
String contentTypeLine = null;
String entityBody = null;

if(fileExists){
statusLine = tokens.nextToken();
contentTypeLine = "Content-type: " + contentType(fileName) + CRLF;
}
else{
statusLine = "HTTP/1.1 404 File Not Found";
contentTypeLine = "Content-type: " + "text/html" + CRLF;
entityBody = "<html><head><title>Not Found </title></head>" +
"<BODY>Not Found</body></html>";
}

//send the status line
os.writeBytes(statusLine);

//send the content Type
os.writeBytes(contentTypeLine);

//send a blank line to indicate the end of the header lines
os.writeBytes(CRLF);

//send the entity Body

if(fileExists){
sendBytes(fis, os);
fis.close();
}
else{
os.writeBytes(entityBody);
os.writeBytes(CRLF);

}

//Close scokets and streams.
fis.close();
os.close();
br.close();
socket.close();

}//end of processRequest

private static String contentType(String fileName){
if(fileName.endsWith(".htm") || fileName.endsWith(".html")){
return "text/html";
}
if(fileName.endsWith(".gif")){
return "image/gif";
}
if(fileName.endsWith(".jpeg") || fileName.endsWith(".jpg")){
return "image/jpeg";
}
return "application/octet-stream";
}// end of contentType

private static void sendBytes(FileInputStream fis, OutputStream os) throws Exception{
//Construct a 1k buffer to hold bytes on their way to the Socket

byte[] buffer = new byte[1024];
int bytes = 0;

//Copy requested file into the scoket's output stream.
while((bytes = fis.read(buffer)) != -1){
os.write(buffer, 0, bytes);
}//end of while
}//end of sendBytes


} // end of the class

当我从 Chrome 网络浏览器发出请求时,代码工作正常。不过,我也制作了WebClient。当我从 WebClient 发出请求时,我被卡住了,因为程序永远运行。

据我跟踪,指针不会从服务器端的 while 循环中的 br.readline 移动。

我的客户的代码如下。

import java.io.*;
import java.net.*;
import java.util.*;

public class WebClient{

final static String CRLF = "\r\n";

public static void main(String [] args) {
String serverName = args[0];
int port = Integer.parseInt(args[1]);
try {
// System.out.println("Connecting to " + serverName + " on port " + port);
Socket client = new Socket(serverName, port);

System.out.println("Just connected to " + client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);

out.writeUTF("GET /" +args[2] +" HTTP/1.1");
out.writeUTF(CRLF);
out.writeUTF("Host: "+client.getLocalSocketAddress());
out.writeUTF(CRLF);
out.writeUTF("Connection: close" + CRLF);
out.writeUTF("User-agent: close" + CRLF);
out.writeUTF(CRLF);

//Cache-Control: max-age=0


System.out.println("Just connected to 1 ");
InputStream inFromServer = client.getInputStream();
System.out.println("Just connected to 2 ");
BufferedReader br = new BufferedReader(new InputStreamReader(inFromServer));
System.out.println("Just connected to 3 ");
String headerLine = null;
while((headerLine = br.readLine()).length()!=0){
System.out.println("asd"+headerLine);
}
System.out.println("Just connected to 4 ");
client.close();
System.out.println("Just connected to 5 ");


} catch (IOException e) {
e.printStackTrace();
}

}

}//end of the class WebClient

谁能帮我解决这个问题。

谢谢。

最佳答案

首先,您必须删除 HttpRequest 中的 fis.close(); 行(就在 os.close(); 之前) code> 类:如果不存在文件,此行会引发 NullPointerException,因为 fis 为空,因此在向浏览器发送 Not Found 响应后,您的服务器不会关闭从该浏览器接受的套接字,这就是为什么即使您在浏览器中看到 Not Found,您的请求也永远不会结束。

其次,您的客户端卡住的原因是您用于发送请求 header 的 writeUTF() 方法。似乎这一行 out.writeUTF(CRLF); 并没有真正发送空字符串,而是添加了一些其他与 UTF 相关的字符(您可能会注意到在服务器的控制台输出中),因此您的服务器陷入 while((headerLine = br.readLine()).length()!=0) 等待客户端发送空字符串,但从未收到它。您需要将 out.writeUTF(CRLF); 替换为 out.writeBytes(CRLF);

此外,使用 BufferedReader 从套接字接收二进制文件没有什么意义。 Reader 通常与字符输入流一起使用,因此它不适用于您的情况。您可以通过替换以下片段来使用 InputStream:

String headerLine = null;
while((headerLine = br.readLine()).length()!=0){
System.out.println("asd"+headerLine);
}

这样(我选择的缓冲区大小为 4096,您可以将其替换为您喜欢的值):

 int readBytes;
byte[] cbuf = new byte[4096];
while((readBytes=inFromServer.read(cbuf, 0, 4096))>-1){
System.out.println("read: " + readBytes);
}

注意:您可能很容易注意到,InputStream.read() 不仅会获取文件本身,还会获取 statusLinecontentTypeLine 和两个 CRLF ,因此如果您想将它们与文件分开,您可以先通过发出两个“readLines”来读取它们,然后仅通过 read() 获取文件

关于java - BufferReader 卡在 readline() 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53055920/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com