我即将进行 Java 编程练习,我希望我的学生自己发现 HTTP 的内在本质,而不是让 URLConnection 为他们完成所有工作。为了估计复杂性,我想出了以下代码片段,它解析回复(恕我直言,这是工作中最难的部分之一),它将返回例如“HTTP/1.1 200 OK”,在中推送诸如“服务器:makato”和“内容长度:1337”之类的内容headers vector 并将 InputStream 保留在内容的第一个字节,以便稍后可以构建 DataInputStream 或 InputStreamReader安全地位于其顶部。
我很想知道对 Java 类有更多经验的人是否可以提出更优雅的替代方案。我不满意的一件事是,每个单独的 is.read() 将不可避免地生成一个额外的系统调用(假设 Socket.getInputStream() 用于提供 is> 论证)。
public static String recvHttpHeaders(InputStream is, Vector<String> headers)
throws Exception {
byte line[] = new byte[512];
String pending=null;
String status=null;
boolean complete=false, CR=false;
int n=0;
while (!complete) {
int x = is.read();
switch(x) {
case -1: throw new Exception("something went wrong");
case '\r':
if (CR) throw new Exception("encoding mismatch CRCR");
CR=true;
break;
case '\n': // bare LF are accepted silently.
String ln = new String(line,0,n,"ASCII");
if (pending!=null) ln = pending + ln;
if (status==null) status = ln;
else headers.add(ln);
complete = ln.length()==0;
pending = null;
n=0; CR=false;
break;
default:
if (CR) throw new Exception("encoding mismatch ?CR");
if (n>=512) {
String part = new String(line, "ASCII");
if (pending!=null) pending += part;
else pending = part;
n=0;
}
line[n++]=(byte)x;
break;
}
}
return status;
}
编辑:不可否认,人们希望在这里使用 xxx.readline() 以避免搞乱线条重建。 BufferedReader(或者实际上任何其他 *Reader)根据一种字符集将字节转换为字符。这意味着如果我在 header 解析中使用该功能,我将不再可以自由地为内容选择该字符集。我还没有发现任何具有内置 readline 功能的字节级类。
性能解决方案:感谢您指出BufferedInputStream。我做了一些额外的测试,确实调用了 as
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
String status = recvHttpHeaders(bis, headers);
rawCopy(bis, output);
确实减少了执行的系统调用量,并且仍然允许我正确接收未经修改的二进制内容。
最佳答案
您应该使用 BufferedReader 来读取文本。包装您的输入流:
BufferedReder br = new BufferedReader(new InputStreamReader(is));
然后使用 readLine() 逐行读取内容:
String line = null;
while((line = br.readLine()) != null) {
// deal with the line
}
关于java - 通过 Java 套接字接收混合媒体。你的更好吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5157574/