java - 通过 Java 套接字接收混合媒体。你的更好吗?

标签 java http sockets character-encoding line

我即将进行 Java 编程练习,我希望我的学生自己发现 HTTP 的内在本质,而不是让 URLConnection 为他们完成所有工作。为了估计复杂性,我想出了以下代码片段,它解析回复(恕我直言,这是工作中最难的部分之一),它将返回例如“HTTP/1.1 200 OK”,在中推送诸如“服务器:makato”“内容长度:1337”之类的内容headers vector 并将 InputStream 保留在内容的第一个字节,以便稍后可以构建 DataInputStreamInputStreamReader安全地位于其顶部。

我很想知道对 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/

相关文章:

java - hibernate 不会创建 hbm2ddl.auto 设置为 "update"的中间表

c# - 我如何使用 fiddlercore 编辑 HTTP 请求 C#

javascript - 除了默默无闻的安全性之外,同源策略还提供什么安全优势?

multithreading - 如何最小化 tcp 服务器应用程序中使用的线程数?

java - 从 Java 服务器发送数据到 ESP8266

apache - 访问服务器外部的localhost

java - 如果哈希码不同,为什么 HashSet 允许相同的项目?

java - PHP/Java 桥 UnsupportedClassVersionError

java - PrintWriter 类未按预期工作

php - 从虚拟主机配置中获取 PHP 中的响应 header