레이블이 http인 게시물을 표시합니다. 모든 게시물 표시
레이블이 http인 게시물을 표시합니다. 모든 게시물 표시

2017년 1월 12일 목요일

web crawler with java

web crawler with java


https://ko.wikipedia.org/wiki/%EC%9B%B9_%ED%81%AC%EB%A1%A4%EB%9F%AC
웹 크롤러(web crawler)는 조직적, 자동화된 방법으로 월드 와이드 웹을 탐색하는 컴퓨터 프로그램입니다.. 웹 크롤러에 대한 다른 용어로는 앤트(ants), 자동 인덱서(automatic indexers), 봇(bots), 웜(worms), 웹 스파이더(web spider), 웹 로봇(web robot) 등이 있습니다.


java로 만든 일단 소스를 아래 공유합니다.
동작은 정해진 http주소를 받아서 web page를 가져와서 파일로 저장하는 소스 입니다. depth를 정해서 html페이지내에 여러개의 링크가 있으면 각 링크들을 방문해서 저장을 하게 됩니다.
결국 웹 페이지를 가져와 저장하는 부분밖에는 없지만 가져온 페이지를 파싱해서 필요한 데이터를 추출하고 분석하는 부분은 용도에 따라 다를 수 있으니 이용자의 몫으로 남겨 두겠습니다.
사용라이브러리는 아래와 같습니다.
httpclient 4.5
commons-cli-1.3.1.jar
jericho-html-3.4.jar

설명은 나중에 추가로 작성하도록 하겠습니다.

소스
package prj.dish;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.zip.GZIPInputStream;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpHost;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import net.htmlparser.jericho.Config;
import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.LoggerProvider;
import net.htmlparser.jericho.Source;

public class Webcrawler {
 private int maxDepth = 1;
 private int maxHostChange = 1;
 private String savePath;
 private String host;
 boolean DOMAIN_CHANGE = true;
 byte[] htmlByte = null;
 HashSet<String> visited = new HashSet<String>();
 CloseableHttpClient httpclient = HttpClients.createDefault();


 public static void main(String[] args) {
  System.out.println("Welcome !! Webcrawler");
  Config.LoggerProvider=LoggerProvider.DISABLED;
  System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.NoOpLog"); 
  if(args.length >= 1){
   Options options = new Options();

   Option savepath = new Option("s", "savepath", true, "input save folder file path");
   savepath.setRequired(true);
   options.addOption(savepath);

   Option url = new Option("u", "url", true, "url ex) http://www.daum.net");
   url.setRequired(true);
   options.addOption(url);

   Option depth = new Option("d", "depth", true, "max depth");
   depth.setRequired(false);
   options.addOption(depth);

   Option changehostdepth = new Option("c", "changehostdepth", true, "change host depth");
   changehostdepth.setRequired(false);
   options.addOption(changehostdepth);

   CommandLineParser parser = new DefaultParser();
   HelpFormatter formatter = new HelpFormatter();
   CommandLine cmd;

   try {
    cmd = parser.parse(options, args);
   } catch (ParseException e) {
    System.out.println(e.getMessage());
    formatter.printHelp("Webcrawler", options);
    System.exit(1);
    return;
   }

   String saveFilePath = cmd.getOptionValue("savepath");
   String urlPath = cmd.getOptionValue("url");
   String depthParam = cmd.getOptionValue("depth");
   if(depthParam==null || depthParam.isEmpty()) depthParam = "2";
   String changehostdepthdepthParam = cmd.getOptionValue("changehostdepth");
   if(changehostdepthdepthParam==null || changehostdepthdepthParam.isEmpty()) changehostdepthdepthParam = "1";
   System.out.println(urlPath);
   Webcrawler crawler;
   crawler = new Webcrawler();
   crawler.setSavePath(saveFilePath);
   crawler.setMaxDepth(Integer.valueOf(depthParam));
   crawler.setMaxHostChange(Integer.valueOf(changehostdepthdepthParam));
   crawler.run(urlPath);
  }
  System.out.println("End Webcrawler");
 }

 private void run(String string) {
  host = string;
  connect( host, "/", 0, 0);
 }
 public String getString() {
  try {
   return new String(htmlByte, "UTF-8");
  } catch (UnsupportedEncodingException e) {
   e.printStackTrace();
  }
  return null;
 }
 private String getHttp(String url) throws IOException, URISyntaxException{
  String ret=null;
  try {
   HttpGet httpGet = new HttpGet(url);
   HttpClientContext context = HttpClientContext.create();
   httpGet.setHeader(HttpHeaders.ACCEPT_ENCODING, "gzip");
   CloseableHttpResponse response = httpclient.execute(httpGet,context);
   try {
    System.out.println(response.getStatusLine());
    HttpEntity entity = response.getEntity();

    Header contentEncoding = response.getFirstHeader("Content-Encoding");
    if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
     System.out.println("gziped");
     htmlByte = inputStreamToByte( new GZIPInputStream(entity.getContent()));
    }else {
     htmlByte = inputStreamToByte(entity.getContent());
    }

    HttpHost target = context.getTargetHost();
    List<URI> redirectLocations = context.getRedirectLocations();
    URI location = URIUtils.resolve(httpGet.getURI(), target, redirectLocations);
    System.out.println("Final HTTP location: " + location.toASCIIString());
    ret = location.toASCIIString();
   } finally {
    response.close();
   }
  } finally {
   //httpclient.close();
  }
  return ret;
 }
 private byte[] inputStreamToByte(InputStream in)
 {
  final int BUF_SIZE = 1024;
  ByteArrayOutputStream out = new ByteArrayOutputStream();
  byte[] buffer = new byte[BUF_SIZE];
  try {
   int length;
   while ((length = in.read(buffer)) != -1) out.write(buffer, 0, length);
  } catch (IOException e) {
   e.printStackTrace();
   return null;
  }
  return out.toByteArray();
 }
 private void connect(String lasturl, String addurl, int depth, int hostchange) {
  Source source = null;
  String newurl = null;
  int hostchanged = 0;

  if(addurl.startsWith("http://") || addurl.startsWith("https://")){
   hostchanged = 1;
   if( maxHostChange <= hostchange+hostchanged) return;
  }
  if( maxDepth <= depth ){
   return;
  }
  try {
   //if(DOMAIN_CHANGE){
   lasturl = calcNextUrl(lasturl, addurl);
   //}else{
   //lasturl = urlChg(host, lasturl, addurl);
   //}
   System.out.println("Get:["+depth+"]:"+lasturl);
   if( !visited.contains(lasturl) ){
    visited.add(lasturl);
   }else{
    System.out.println("visited !");
    return;
   }
   //source=new Source(new URL(lasturl));
   newurl = getHttp(lasturl);
   //fileSave(savePath + changeFileName(lasturl)+".htm",getString());
   fileSave(savePath + changeFileName(lasturl)+".htm",htmlByte);
   source=new Source(getString());

  } catch (Exception e) {
   e.printStackTrace();
   return;
  }
  //System.out.println(source.getRenderer().toString());
  List <Element> elements = source.getAllElements("a");
  System.out.println("Len:("+htmlByte.length+"), A tag("+elements.size()+")");
  for(int i = 0 ; i < elements.size(); i++){
   Element ele = elements.get(i);
   String href = ele.getAttributeValue("href");
   if(href==null || href.isEmpty()) continue;
   if(!DOMAIN_CHANGE){
    if(href.startsWith("http://") || href.startsWith("https://")){
     continue;
    }
   }
   if(href.startsWith("javascript:")){
    continue;
   }else if(href.contains("#")){
    continue;
   }else if(href.startsWith("<")){
    continue;
   }
   connect(newurl,href,depth+1,hostchange+hostchanged);
  }
 }

 private void fileSave(String name, byte[] htmlByte) {
  FileOutputStream stream = null;
  try{
   stream = new FileOutputStream(name);
   stream.write(htmlByte);
  } catch (Exception e) {
  } finally {
   try {
    stream.close();
   } catch (IOException e) {
   }
  }
 }

 private String changeFileName(String lasturl) {
  lasturl=lasturl.replace('?', '_');
  lasturl=lasturl.replace('*', '_');
  lasturl=lasturl.replace('%', '_');
  lasturl=lasturl.replace('.', '_');
  lasturl=lasturl.replace('/', '_');
  lasturl=lasturl.replace('\\', '_');
  lasturl=lasturl.replace('\"', '_');
  lasturl=lasturl.replace('\'', '_');
  lasturl=lasturl.replace('|', '_');
  lasturl=lasturl.replace('+', '_');
  lasturl=lasturl.replace('-', '_');
  lasturl=lasturl.replace(':', '_');
  return lasturl;
 }

 private void setMaxDepth(int i) {
  maxDepth = i;
 }

 private void setMaxHostChange(int i) {
  maxHostChange = i;
 }

 private void setSavePath(String string) {
  savePath = string;
  if(!savePath.endsWith("/")) savePath=savePath+"/";
  createDirectoryIfNeeded(string);
  String timeStamp = new SimpleDateFormat("yyyy.MM.dd.HH.mm").format(new Date());
  savePath=savePath+timeStamp;
  createDirectoryIfNeeded(savePath);
  if(!savePath.endsWith("/")) savePath=savePath+"/";
 }

 private void createDirectoryIfNeeded(String directoryName)
 {
  File theDir = new File(directoryName); 
  if (!theDir.exists())
   theDir.mkdirs();
 }

 private void Webcrawler() {
 }

 public static String calcNextUrl(String thisurl, String add)
 {
  System.out.println("This:["+thisurl + "]Add:["+add+"]");
  URI thisuri = URI.create(thisurl);
  String data = thisuri.getScheme() + "://" + thisuri.getHost();
  if(thisuri.getPort()!=-1) data=":"+thisuri.getPort();
  if(add.startsWith("/")) data=data+add;
  else if(add.startsWith("http")) data=add;
  else {
   data=thisurl;
   if(data.endsWith("/")) data=data+add;
   else data=data+"/"+add;
  }

  URI returi = URI.create(data);
  returi = returi.normalize();
  if( !returi.toString().startsWith("http") ){
   System.out.println("Error");
  }
  return returi.toString();
 }

 public static void fileSave(String name,String data)
 {
  try {
   File newTextFile = new File(name);
   FileWriter fw = new FileWriter(newTextFile);
   fw.write(data);
   fw.close();
  } catch (IOException iox) {
   iox.printStackTrace();
  }
 }
}


실행할때 아래와 같이 옵션을 주어야 합니다.
-u 는 접속시도하는 url이 됩니다.
-s 는 저장할 폴더 이름입니다.
-d 이건 최대 html의 depth를 의미합니다. 숫자가 크면 링크를 많이 타고 갑니다. 따라서 적당하게 적습니다.
-c 링크를 타고 갈때 다른 site가 나올수 있는데 몇번이나 허용할지 최대 허용 갯수를 의미합니다.

-u http://www.daum.net -s save -d 2 -c 1

실행화면
Welcome !! Webcrawler
http://www.daum.net
This:[http://www.daum.net]Add:[/]
Get:[0]:http://www.daum.net/
HTTP/1.1 200 OK
Final HTTP location: http://www.daum.net/
Len:(154748), A tag(170)
This:[http://www.daum.net/]Add:[/doc/top_accessibility.html]
Get:[1]:http://www.daum.net/doc/top_accessibility.html
HTTP/1.1 200 OK
Final HTTP location: http://www.daum.net/doc/top_accessibility.html
Len:(28899), A tag(40)
End Webcrawler

코드 설명
http://swlock.blogspot.com/2017/01/web-crawler-with-java_20.html


2016년 12월 18일 일요일

httpclient(http)사용시 page이동(html page 요청할때 상대 주소와 절대 주소 처리)

httpclient를 사용하는 이유는 주로 webpage를 java를 이용해서 접속을 할때 사용하게 됩니다. 사용하다가 몇가지 중요한 사실을 알게되었는데요. 여기에 정리하여 봅니다.
해당내용은 httpclient에 국한 되는 내용은 아니고 html page를 직접 받아서 처리할때 알아두어야 하는 내용입니다.

1) 상대주소와 절대주소

Page를 web에서 절대 주소를 나타낼때는 '/' 를 사용하게 됩니다.
http://abc.com/aaa/index.html 라고 요청한 페이지에서 abc.com이 host 주소가 되고 /next.html 링크를 요청했다면 http://abc.com/next.html 이 요청되어질 것입니다.
http://abc.com/aaa/index.html 라고 요청한 페이지에서 ../next.html 이 요청되어지면 http://abc.com/aaa/../next.html 이게 되면서 http://abc.com/next.html 이 요청되어 집니다. 하지만 http GET 호출시 http://abc.com/aaa/../next.html 이런식으로 호출 되면 서버쪽에서 .. 처리를 해야하는데 일반적으로 처리하지 못하는 서버가 발생합니다.

정리
last url : abc.com/aaa/index.html
host : abc.com
get : /next.html => abc.com/next.html
page : abc.com/next.html

last url : abc.com/aaa/index.html
host : abc.com
get : ../next.html => abc.com/next.html
page : abc.com/next.html

2) URI normalize

따라서 http client로 page요청을 할때 ".." "." 경로를 정리해주어야 합니다.
이 과정을 normalize라고 합니다.
두가지를 구현하여 보았습니다. urlChg라는 메소드는 host와 이전 요청된 url을 인자로 넣고 atag의 href 주소를 넣으면 get해야하는 경로를 얻게 됩니다.
설명이 장황하고 길게 느껴질지 모르나, host는 절대 경로를 사용할때 사용하는 최상위 주소가 됩니다

import java.lang.String;
import java.net.URI;

// one class needs to have a main() method
public class HelloWorld
{
  // arguments are passed using the text field below this editor
  public static void main(String[] args)
  {
    System.out.println(normalize("http://abc.com/aaa/../next.html"));
    System.out.println(urlChg("http://abc.com","http://abc.com/aaa/index.html","../next.html"));
    System.out.println(urlChg("http://abc.com","http://abc.com/aaa/index.html",".././abc/../next.html"));
    System.out.println(urlChg("http://abc.com","http://abc.com/aaa/index.html","next.html"));
    System.out.println(urlChg("http://abc.com","http://abc.com/aaa/index.html","/next.html"));
    System.out.println(urlChg("http://abc.com","http://abc.com/aaa/","/next.html"));
    System.out.println(urlChg("http://abc.com","http://abc.com/aaa/","next.html"));
  }
  public static String urlChg(String host, String url, String add)
  {
    if(add.startsWith("/")){
      return host+add;
    }else{
      if(url.endsWith("/")){
        return url+add;
      }
    }
    String str = url.substring(0,url.lastIndexOf('/'))+"/"+add;
    URI uri = URI.create(str);
    uri=uri.normalize();
    return uri.toString();
  }
  public static String normalize(String str)
  {
    URI uri = URI.create(str);
    uri=uri.normalize();
    return uri.toString();
  }
}
------------------------------- result http://abc.com/next.html http://abc.com/next.html http://abc.com/next.html http://abc.com/aaa/next.html http://abc.com/next.html http://abc.com/next.html http://abc.com/aaa/next.html

위 내용에 문제가 있어서 추가로 구현하였습니다.
add되는 주소가 새로운 scheme로 시작되는 경우 즉 http,https등으로 site가 변경되는 경우
위 메소드에서는 제대로 처리하지 못하였습니다.
또한 인자가 2개가 있어서 host를 미리 저장하고 있어야 하는 문제도 해결하였습니다.
package test;

import java.net.URI;
import java.util.List;

public class Test {
 public static void main(String[] args) {
  System.out.println(calcNextUrl("http://www.a.b.c/","abc/def/ghi"));
  System.out.println(calcNextUrl("http://www.a.b.c/abc","def/ghi"));
  System.out.println(calcNextUrl("http://www.a.b.c/abc","/def/ghi"));
  System.out.println(calcNextUrl("http://www.a.b.c/abc","../def/ghi"));
  System.out.println(calcNextUrl("http://www.a.b.c/abc","http://d.e.f/def/ghi"));
 }
 public static String calcNextUrl(String thisurl, String add)
 {
  System.out.println("This:["+thisurl + "] + Add:["+add+"]");
  URI thisuri = URI.create(thisurl);
  String data = thisuri.getScheme() + "://" + thisuri.getHost();
  if(thisuri.getPort()!=-1) data=":"+thisuri.getPort();
  if(add.startsWith("/")) data=data+add;
  else if(add.startsWith("http")) data=add;
  else {
   data=thisurl;
   if(data.endsWith("/")) data=data+add;
   else data=data+"/"+add;
  }

  URI returi = URI.create(data);
  returi = returi.normalize();
  if( !returi.toString().startsWith("http") ){
   System.out.println("Error");
  }
  return returi.toString();
 }
}

결과
This:[http://www.a.b.c/] + Add:[abc/def/ghi]
http://www.a.b.c/abc/def/ghi
This:[http://www.a.b.c/abc] + Add:[def/ghi]
http://www.a.b.c/abc/def/ghi
This:[http://www.a.b.c/abc] + Add:[/def/ghi]
http://www.a.b.c/def/ghi
This:[http://www.a.b.c/abc] + Add:[../def/ghi]
http://www.a.b.c/def/ghi
This:[http://www.a.b.c/abc] + Add:[http://d.e.f/def/ghi]
http://d.e.f/def/ghi


3) HTTP redirection

HTTP response의 302,301 응답은 redirection이며 page를 자동으로 다음 페이지를 이동해서 요청을 해야합니다.
하지만 httpclient를 사용하면 자동으로 다음 페이지가 로딩됩니다. 단 GET 요청일때만 그렇습니다. POST 로 page를 요청했다면 직접 구현해야합니다.
그래서 다음 페이지가 로딩될때 자동으로 요청되어지면 page의 경로가 변경되게 되면 앞에서 설명한 상대 주소의 다음 link를 get할때 어려움이 있습니다. 따라서 execute가 되고나면 host와 get한 페이지 정보를 얻어오는 함수를 이용하여 마지막에 요청된 page가 어디인지 저장해 두어야 합니다.

2016년 7월 10일 일요일

http session 유지 html 접속


앞에서 android 에서 session을 유지하면서(login) 하는 소스를 만들었습니다.
http://swlock.blogspot.kr/2015/03/httpurlconnection.html
하지만 사용하다 보니 문제가 있었습니다.

saveCookie 함수인데요. Set-Cookie 값을 가져오지 않으면 m_session의 값이 false가 되어버려 다음번 연결시제대로 동작되지 않는 현상이 있습니다.
재현경로는 로그인 페이지 접속 후 곧장 다른페이지 접속시에는 문제없으나, 그 이후에 다른페이지 접속하면 문제가 발생합니다.
 public void saveCookie( HttpURLConnection conn)
 {
  
     Map<String, List<String>> imap = conn.getHeaderFields( ) ;
     if( imap.containsKey( "Set-Cookie" ) )
     {
         List<String> lString = imap.get( "Set-Cookie" ) ;
         for( int i = 0 ; i < lString.size() ; i++ ) {
             m_cookies += lString.get( i ) ;
         }
         m_session = true ;
     } else {
         m_session = false ;
     }
 }

해당 내용 수정한 전체 소스 입니다.

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Map;

import android.util.Log;

public class GetHttp {

 final static double VERSION = 1.20160710;
 static final int ERROR_CODE_HTTP_NOT_FOUND = -404;
 static final int ERROR_CODE_HTTP_UNAUTHORIZED = -401;
 static final int ERROR_CODE_HTTP_ELSE = -1;
 static final int ERROR_CODE_HTTP_EXCEPTION = -1000;
 static final int ERROR_CODE_NOERROR = 0;
 static boolean DEBUG_ON = false;
 byte[] htmlByte = null;
 int errorCode = 0;
 boolean bUseCache = true;
 boolean m_session = false;
 String m_cookies = "";
 public String getString() {
  try {
   return new String(htmlByte, "UTF-8");
  } catch (UnsupportedEncodingException e) {
   e.printStackTrace();
  }
  return null;
 }
 public byte[] getByte() {
  return htmlByte;
 }
 public int getErrorCode() {
  return errorCode;
 }
 public boolean execute(String addr) {
  return execute(addr, 5, 10);
 }
 public void saveCookie( HttpURLConnection conn)
 {

  Map<String, List<String>> imap = conn.getHeaderFields( ) ;
  if( imap.containsKey( "Set-Cookie" ) )
  {
   List<String> lString = imap.get( "Set-Cookie" ) ;
   for( int i = 0 ; i < lString.size() ; i++ ) {
    m_cookies += lString.get( i ) ;
   }
   if( DEBUG_ON ) Log.e("TAG",m_cookies);
   m_session = true ;
  }
 }
 // 참고 소스:http://markan82.tistory.com/32
 public boolean execute(String addr, int connTimeOutSec, int readTimeOutSec) {
  boolean retval = true;
  errorCode = ERROR_CODE_NOERROR;
  try {
   URL url = new URL(addr);
   if( DEBUG_ON ) Log.e("TAG",addr);
   HttpURLConnection conn = (HttpURLConnection) url.openConnection();
   if( conn != null ) {
    conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
    if( m_session ) {
     conn.setRequestProperty( "Cookie", m_cookies );
    }
    conn.setConnectTimeout(1000*connTimeOutSec);
    conn.setReadTimeout(1000*readTimeOutSec);
    conn.setUseCaches(bUseCache);
    conn.setDoInput(true);

    int resCode = conn.getResponseCode();
    saveCookie(conn);

    if( resCode == HttpURLConnection.HTTP_OK ) {
     htmlByte = inputStreamToByte(conn.getInputStream());
     if(htmlByte == null || htmlByte.length == 0){
      errorCode = ERROR_CODE_HTTP_ELSE;
      retval = false;
     }
    } else if( resCode == HttpURLConnection.HTTP_NOT_FOUND ) {
     errorCode = ERROR_CODE_HTTP_NOT_FOUND;
     retval = false;
    } else if( resCode == HttpURLConnection.HTTP_UNAUTHORIZED ) {
     errorCode = ERROR_CODE_HTTP_UNAUTHORIZED;
     retval = false;
    } else {
     errorCode = ERROR_CODE_HTTP_ELSE;
     retval = false;
    }
    // DISCONNECT
    conn.disconnect();
   } else {
    errorCode = ERROR_CODE_HTTP_ELSE;
    retval = false;
   }
  } catch(Exception e) {
   e.printStackTrace();
   errorCode = ERROR_CODE_HTTP_EXCEPTION;
   retval = false;
  }
  return retval;
 }
 private byte[] inputStreamToByte(InputStream in)
 {
  final int BUF_SIZE = 1024;
  ByteArrayOutputStream out = new ByteArrayOutputStream();
  byte[] buffer = new byte[BUF_SIZE];
  try {
   int length;
   while ((length = in.read(buffer)) != -1) out.write(buffer, 0, length);
  } catch (IOException e) {
   e.printStackTrace();
   return null;
  }
  return out.toByteArray();
 }
}


추가내용
위에서 쿠키 작업한 내용이 완벽하지 않습니다. 
https://en.wikipedia.org/wiki/HTTP_cookie 
https://tools.ietf.org/html/rfc2109
여기 보면 자세한 내용이 나오는데 안의 인자값에 따라 어떤 동작들을 해야합니다. 그러한 부분이 전혀 구현되어있지 않습니다.
따라서 완벽하게 하려면 httpclient libarary등의 라이브러리를 사용하시기 바랍니다.
http://swlock.blogspot.kr/2017/01/httpclient-use-in-android-httpclient.html