socket模擬http傳送請求
阿新 • • 發佈:2019-02-07
import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; import java.util.ArrayList; /** * 一個簡單的HTTP客戶端,的作用 * 和httpUrlConnection,HttpClient * ,AsycnHttpClient, * xutils中httpUtils是一樣的。 * 傳送HTTP請求,模擬瀏覽器 * 可列印伺服器傳送過來的HTTP訊息 */ public class SimpleHttpClient { private static String encoding = "GBK"; public void send(String ip,int port,String url,String sendData) { try { //http連線(短連線,缺點每次再連,佔用時間):http定義請求由三部分組成,返回的內容由三部分組成 //http傳送的內容由socket傳送 //socket連線 Socket socket = new Socket(ip, port); OutputStreamWriter osw = new OutputStreamWriter(socket.getOutputStream()); StringBuffer sb = new StringBuffer(); //http協議中請求行 sb.append("GET "+url+" HTTP/1.1\r\n"); //http協議中請求頭 sb.append("Host: "+ip+"\r\n"); sb.append("Connection: Keep-Alive\r\n"); sb.append("user-agent: 1601\r\n"); //注,這是關鍵的關鍵,忘了這裡讓我搞了半個小時。這裡一定要一個回車換行,表示訊息頭完,不然伺服器會等待 sb.append("\r\n"); osw.write(sb.toString()); osw.flush(); //--輸出伺服器傳回的訊息的頭資訊 InputStream is = socket.getInputStream(); String line = null; int contentLength = 0;//伺服器傳送回來的訊息長度 // 讀取所有伺服器傳送過來的請求引數頭部資訊 do { line = readLine(is, 0); //如果有Content-Length訊息頭時取出 if (line.startsWith("Content-Length")) { contentLength = Integer.parseInt(line.split(":")[1].trim()); } //列印請求部資訊 System.out.print(line); //如果遇到了一個單獨的回車換行,則表示請求頭結束 } while (!line.equals("\r\n")); //--輸訊息的體 System.out.print(readLine(is, contentLength)); //關閉流 is.close(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { SimpleHttpClient httpClient=new SimpleHttpClient(); //遠端 124.207.192.18 //本地班172.60.5.100 httpClient.send("172.60.5.100", 8080, "/allRunServer/login.html", null); } /* * 這裡我們自己模擬讀取一行,因為如果使用API中的BufferedReader時,它是讀取到一個回車換行後 * 才返回,否則如果沒有讀取,則一直阻塞,直接伺服器超時自動關閉為止,如果此時還使用BufferedReader * 來讀時,因為讀到最後一行時,最後一行後不會有回車換行符,所以就會等待。如果使用伺服器傳送回來的 * 訊息頭裡的Content-Length來擷取訊息體,這樣就不會阻塞 * * contentLe 引數 如果為0時,表示讀頭,讀時我們還是一行一行的返回;如果不為0,表示讀訊息體, * 時我們根據訊息體的長度來讀完訊息體後,客戶端自動關閉流,這樣不用先到伺服器超時來關閉。 */ private static String readLine(InputStream is, int contentLe) throws IOException { ArrayList lineByteList = new ArrayList(); byte readByte; int total = 0; if (contentLe != 0) { do { readByte = (byte) is.read(); lineByteList.add(Byte.valueOf(readByte)); total++; } while (total < contentLe);//訊息體讀還未讀完 } else { do { readByte = (byte) is.read(); lineByteList.add(Byte.valueOf(readByte)); } while (readByte != 10); } byte[] tmpByteArr = new byte[lineByteList.size()]; for (int i = 0; i < lineByteList.size(); i++) { tmpByteArr[i] = ((Byte) lineByteList.get(i)).byteValue(); } lineByteList.clear(); return new String(tmpByteArr, encoding); } }
import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; import java.util.ArrayList; /** * 一個簡單的HTTP客戶端, * 傳送HTTP請求,模擬瀏覽器 * 可列印伺服器傳送過來的HTTP訊息 */ public class ConnectMyWebServer { private static String encoding = "GBK"; public static void main(String[] args) { try { //本地班124.207.192.18改成172.60.5.100 Socket socket = new Socket("172.60.50.223", 8080); OutputStreamWriter osw = new OutputStreamWriter(socket.getOutputStream()); StringBuffer sb = new StringBuffer(); sb.append("GET /index.html HTTP/1.1\r\n"); sb.append("Host: 172.60.50.223\r\n"); sb.append("Connection: Keep-Alive\r\n"); sb.append("user-agent: simpleHttpClinet zhangjiujun\r\n"); //注,這是關鍵的關鍵,忘了這裡讓我搞了半個小時。這裡一定要一個回車換行,表示訊息頭完,不然伺服器會等待 sb.append("\r\n"); osw.write(sb.toString()); osw.flush(); //--輸出伺服器傳回的訊息的頭資訊 InputStream is = socket.getInputStream(); String line = null; int contentLength = 0;//伺服器傳送回來的訊息長度 // 讀取所有伺服器傳送過來的請求引數頭部資訊 do { line = readLine(is, 0); //如果有Content-Length訊息頭時取出 if (line.startsWith("Content-Length")) { contentLength = Integer.parseInt(line.split(":")[1].trim()); } //列印請求部資訊 System.out.print(line); //如果遇到了一個單獨的回車換行,則表示請求頭結束 } while (!line.equals("\r\n")); //--輸訊息的體 System.out.print(readLine(is, contentLength)); //關閉流 is.close(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /* * 這裡我們自己模擬讀取一行,因為如果使用API中的BufferedReader時,它是讀取到一個回車換行後 * 才返回,否則如果沒有讀取,則一直阻塞,直接伺服器超時自動關閉為止,如果此時還使用BufferedReader * 來讀時,因為讀到最後一行時,最後一行後不會有回車換行符,所以就會等待。如果使用伺服器傳送回來的 * 訊息頭裡的Content-Length來擷取訊息體,這樣就不會阻塞 * * contentLe 引數 如果為0時,表示讀頭,讀時我們還是一行一行的返回;如果不為0,表示讀訊息體, * 時我們根據訊息體的長度來讀完訊息體後,客戶端自動關閉流,這樣不用先到伺服器超時來關閉。 */ private static String readLine(InputStream is, int contentLe) throws IOException { ArrayList lineByteList = new ArrayList(); byte readByte; int total = 0; if (contentLe != 0) { do { readByte = (byte) is.read(); lineByteList.add(Byte.valueOf(readByte)); total++; } while (total < contentLe);//訊息體讀還未讀完 } else { do { readByte = (byte) is.read(); lineByteList.add(Byte.valueOf(readByte)); } while (readByte != 10); } byte[] tmpByteArr = new byte[lineByteList.size()]; for (int i = 0; i < lineByteList.size(); i++) { tmpByteArr[i] = ((Byte) lineByteList.get(i)).byteValue(); } lineByteList.clear(); return new String(tmpByteArr, encoding); } }