我正在为学校项目使用多线程Web服务器。我应该能够在浏览器中进入localhost并请求3个不同的文件(.htm,.jpeg,.pdf)。但是,当我对同时包含图片的.htm文件执行此操作时(2个请求),该.htm文件出现在浏览器中,但是每次尝试在图片上执行写入操作时,我都会遇到很多管道异常的异常(分配要求一次写入1024个字节)。我实现此方法的方式显然出了问题,但是当我尝试为第二个文件编写时,我对连接在何处关闭感到迷茫?
我尝试了几种不同的方法来尝试解决此问题,包括在尝试读取套接字输入流时进行循环,但是我认为这样做违反了多线程服务器的目的。
服务器:
while(true){
try {
sock = servSock.accept(); // Handles the connection
// Connection received log
System.out.println("Connection received: " + new Date().toString() + " at " + sock.getInetAddress() + sock.getPort());
HTTP pro = new HTTP(sock); // Client handler
pro.run();
ServerThread serverThread = new ServerThread(pro);
// Starts ServerThread
serverThread.start();
} catch (Exception e){
System.out.println(e);
}
}
HTTP:
public void run(){
// Try to open reader
try{
readSock = new BufferedReader(new InputStreamReader(sock.getInputStream()));
} catch (Exception e){
System.out.println(e);
}
// Open output stream
try{
this.out = new DataOutputStream(sock.getOutputStream());
this.printOut = new PrintWriter(sock.getOutputStream());
} catch (Exception e){
System.out.println(e);
}
// Try to read incoming line
try {
this.reqMes = readSock.readLine();
} catch (IOException e) {
e.printStackTrace();
}
StringTokenizer st = new StringTokenizer(reqMes);
// Parse the request message
int count = 0;
while(st.hasMoreTokens()){
String str = st.nextToken();
if (count == 1){
this.fileName = "." + str;
}
count += 1;
}
System.out.println("File name received.");
File file = null;
try {
file = new File(this.fileName);
this.f = new FileInputStream(file); // File input stream
this.fileExists = true;
System.out.println("File " + this.fileName + " exists.");
} catch (FileNotFoundException e) {
System.out.println(e);
this.fileExists = false;
System.out.println("File does not exist.");
}
byte[] buffer = new byte[1024];
// Write status line
if (this.fileExists) {
System.out.println("Trying to write data");
try{
this.out.writeBytes("HTTP/1.0 " + "200 OK " + this.CRLF);
this.out.flush();
this.printOut.println("HTTP/1.0 " + "200 OK " + this.CRLF);
// Write Header
this.out.writeBytes("Content-type: " + getMime(this.fileName) + this.CRLF);
this.printOut.println("Content-type: " + getMime(this.fileName) + this.CRLF);
this.out.flush();
// Read file data
byte[] fileData = new byte[1024];
while (this.f.read(fileData) != -1) {
// Write File data
try{
this.out.write(fileData,0,1024);
this.out.flush(); // Flush output stream
} catch (IOException e) {
System.out.println(e);
}
}
System.out.println("Flushed");
} catch (IOException e) {
e.printStackTrace();
}
}
对于浏览器中的一个.htm文件,该文件和html看起来似乎不错。但是看起来它再次请求html文件中的.jpeg文件,并且浏览器陷入了用java.net.SocketException加载的麻烦:每次在
处写入数据时,管道损坏(写入失败)。this.out.write(fileData,0,1024);
感谢您的帮助。
答案 0 :(得分:0)
在对不同问题进行了大量搜索之后,我找到了答案here。
问题在于响应头的格式不正确,导致连接过早终止。 必须在标头之后发送另一个空行(“ \ r \ n”)。
以下代码现在有效(this.CRLF等于“ \ r \ n”):
public void run(){
// Try to open reader
try{
readSock = new BufferedReader(new InputStreamReader(sock.getInputStream()));
} catch (Exception e){
System.out.println(e);
}
// Open output stream
try{
this.out = new DataOutputStream(sock.getOutputStream()); // Data output
this.printOut = new PrintWriter(sock.getOutputStream()); // Print output
} catch (Exception e){
System.out.println(e);
}
// Try to read incoming line
try {
this.reqMes = readSock.readLine();
} catch (IOException e) {
e.printStackTrace();
}
StringTokenizer st = new StringTokenizer(reqMes);
// Parse the request message
int count = 0;
while(st.hasMoreTokens()){
String str = st.nextToken();
if (count == 1){
this.fileName = "." + str;
}
count += 1;
}
System.out.println("File name received.");
// Initialize file to be sent
File file = null;
// Try to find file and create input stream
try {
file = new File(this.fileName);
this.f = new FileInputStream(file); // File input stream
this.fileExists = true;
System.out.println("File " + this.fileName + " exists.");
} catch (FileNotFoundException e) {
System.out.println(e);
this.fileExists = false;
System.out.println("File does not exist.");
}
byte[] buffer = new byte[1024];
// Write status line
if (this.fileExists) {
System.out.println("Trying to write data");
try{
this.out.writeBytes("HTTP/1.0 " + "200 OK " + this.CRLF);
this.out.flush();
// Write Header
this.out.writeBytes("Content-type: " + getMime(this.fileName) + this.CRLF);
this.out.flush();
this.out.writeBytes(this.CRLF);
this.out.flush();
// Read file data
byte[] fileData = new byte[1024];
int i;
while ((i = this.f.read(fileData)) > 0) {
// Write File data
try{
this.out.write(fileData,0, i);
} catch (IOException e) {
System.out.println(e);
}
}
this.out.flush(); // Flush output stream
System.out.println("Flushed");
closeSock(); // Closes socket
} catch (IOException e) {
e.printStackTrace();
}