Я собираюсь дать упражнение по программированию на Java, и я бы хотел, чтобы мои студенты сами открыли для себя сущность HTTP, а не чтобы URLConnection делал всю работу за них.Чтобы оценить сложность, я придумал следующий фрагмент, который анализирует ответ (imho, одна из самых сложных частей задания), который возвращает, например, "HTTP / 1.1 200 OK" ,добавьте в вектор заголовки * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * вз} проб}первый байт содержимого, так что DataInputStream или InputStreamReader впоследствии можно безопасно построить поверх него.
Мне интересно знать, если кто-то сбольше опыта классов Java может предложить более элегантные альтернативы.Одна вещь, которая меня не устраивает, заключается в том, что каждый отдельный is.read () неизбежно будет генерировать дополнительный системный вызов (при условии, что Socket.getInputStream () используется для подачи , это аргумент).
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;
}
edit : по общему признанию, здесь хотелось бы использовать xxx.readline () , чтобы избежать путаницы с реконструкцией линий.BufferedReader (или любой другой * Reader, фактически) преобразует байты в символы в соответствии с одной кодировкой.Это означает, что я больше не могу выбирать этот набор символов для содержимого, если я использовал эту функцию при разборе заголовка.Я не нашел ни одного класса уровня байтов со встроенной способностью чтения.
решение для повышения производительности : Спасибо за указание на BufferedInputStream.Я сделал несколько дополнительных тестов, и, действительно, вызов как
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
String status = recvHttpHeaders(bis, headers);
rawCopy(bis, output);
действительно уменьшает количество выполняемых системных вызовов и все еще позволяет мне правильно получать двоичный контент без изменений.