套接字在尝试从web浏览器Java读取输入流时挂起



我正试图从web浏览器客户端提供的套接字读取输入流。到目前为止,我采取的每一种方法都得到了相同的结果,只是悬而未决,我不知道为什么。我已经尝试过mark()将读取限制标记为可用内容,但仍然没有成功。

inputStream.mark(inputStream.available());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024 * 9];
int read;
while((read = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, read);
}
byte[] bytes = outputStream.toByteArray();

我也尝试过clientSocket.shutdownInput()来解决这个问题,但仍然没有效果。

下面是我的尝试:

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
public class Server {
public static void main(String[] args)
{
ServerSocket server = null;
try {
// Server is listening on port 3001
server = new ServerSocket(3001, 1, InetAddress.getByName("localhost"));
server.setReuseAddress(true);
// running infinite loop for getting
// client request
while (true) {
// socket object to receive incoming client
// requests
Socket client = server.accept();
// Displaying that new client is connected
// to Server
System.out.println("New client connected"
+ client.getInetAddress()
.getHostAddress());

// create a new thread object
ClientHandler clientSock
= new ClientHandler(client);
// This thread will handle the client
// separately
new Thread(clientSock).start();
}
}catch (IOException e) {
e.printStackTrace();
}
}
// ClientHandler class
private static class ClientHandler implements Runnable {
private final Socket clientSocket;
// Constructor
public ClientHandler(Socket clientSocket)
{
this.clientSocket = clientSocket;
}
public void run() {

InputStream inputStream = null;
OutputStream clientOutput = null;
try {
inputStream = clientSocket.getInputStream();
inputStream.mark(inputStream.available());
clientSocket.shutdownInput();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024 * 9];
int numRead;
while((numRead = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, numRead);
}
byte[] bytes = outputStream.toByteArray();
String payloadString = new String(bytes, StandardCharsets.UTF_8);
System.out.println(payloadString);
clientOutput = clientSocket.getOutputStream();
clientOutput.write(("HTTP/1.1 rn" + "200 OK").getBytes());
clientOutput.write(("ContentType: " + "text/html" + "rn").getBytes());
clientOutput.write("rn".getBytes());
clientOutput.write("Hello World!".getBytes());
clientOutput.write("rnrn".getBytes());
clientOutput.flush();
inputStream.close();
clientOutput.close();
try{
clientSocket.close();
}catch(Exception ex){
ex.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

任何帮助都将不胜感激!非常感谢。

浏览器建议您应该把这些都扔进垃圾桶并使用HTTP,因为浏览器。

但是,如果你坚持的话,这里有两个问题。

  1. 你把事情搞得太复杂了

你可以把所有的代码都替换成这行简单的代码:

byte[] bytes = in.readAllBytes();

它替换了以in.mark(in.available())开头的行(这一行什么都不做,我不知道你是从哪里得到的。如果你认为它应该做一些特定的事情,你可能想提到它。因为它什么也不做。如果你曾经做过resetmark很有用,但你没有,你不需要在这里,因此,没有用(,一直到"byte[]字节=。。。;

  1. 套接字不会关闭,除非发送方尽力关闭它

您的读取代码(您的,或上面简单得多的一行代码(读取所有内容,直到流关闭。在第二个片段中,您立即关闭它,这显然不起作用。您无法知道何时关闭它,发件人会执行此任务。显然它没有这么做。

我建议您调整预卷大小的协议,这样您就知道要读取多少,而不必仅仅为了发出数据已发送的信号而关闭套接字。

例如:

byte[] sizeRaw = in.readNBytes(4);
int size = ByteBuffer.wrap(bytes).getInt();
byte[] bytes = in.readNBytes(size);

当然,您必须调整发送代码才能首先发送大小(作为32位值,big-endian(。无论如何,你必须在这里查看发送代码。要么修复它,使其在完成后关闭,要么更好的是,调整它,使它先发送大小。

最新更新