黑馬程序員-JAVA網絡編程

------- android培訓java培訓、期待與您交流! ----------

1,網絡通訊中的三個要素

     IP地址

         網絡中設備的標識

         不宜記憶,可用主機名

         本地迴環地址:127.0.0.1主機名:localhost

      端口號

          用於標識進程的邏輯地址,不同進程的標識

          有效端口:0-65535,其中,0-1024系統使用或者保留端口子

      傳輸協議

          通訊規則

          常見協議:TCP,UDP

2,IP簡述使用:

  

  import java.net.InetAddress;
    import java.net.UnknownHostException;


  public class Test1 {
    public static void main(String[] args) {
   try {
    //本地主機ip地址對象
   InetAddress ip=InetAddress.getLocalHost();
   //獲取其他主機ip地址對象
   ip=InetAddress.getByName("192.168.100");
   System.out.println(ip.getHostAddress());//地址
   System.out.println(ip.getHostName());//主機名
  
   } catch (UnknownHostException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
   }
  }
 }


 

  3,UDP,TCP,Socket

    UDP

         將數據及源和目的封裝成數據包中,不需要建立連接

         每個數據包的大小限制在64k內

         因爲無連接,是不可靠協議

         不需要建立連接,速度快

   TCP

      建立連接,形成傳輸數據的通道

      在連接中進行大數據傳輸

      通過三次握手完成連接,是可靠協議

      必須建立連接,效率會稍低
   Socket

      就是爲網絡服務提供一種機制

      通信的兩端都有Socket。//只要有了它,才能進行連接,連接後纔有通路,現有碼頭,再有船

      網絡通信其實就是Socket間的通信

      數據在兩個Socket間通過IO傳輸

      理解:港口,插座,應用程序通信,Socket有了,但是傳輸協議不一樣,每個傳輸協議都有自己的建立端點的方式,udp,tcp

4,兩個類

   DatagramSocket

    

 

DatagramPacket

5,UDP建立發送端

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

/*
 * 需求:通過udp傳輸方式,將一段文字數據發送出去
 * 1,建立udpSocket服務
 * 2,提供數據,並將數據封裝到數據包中。
 * 3,通過socket服務的發送功能,將數據發出去
 * 4,關閉資源
 */
public class UdpSend {
 public static void main(String[] args) {
  try {
   // 創建udp服務通過DatagramSocket對象
   DatagramSocket ds = new DatagramSocket(8888);//可以不指定,系統隨機分配
   // 確定數據,將數據封裝成包
   byte[] b = "aaa".getBytes();
   try {
    DatagramPacket dp = new DatagramPacket(b, b.length, InetAddress
      .getByName("192.168.1.100"), 10000);

    ds.send(dp);// 通過socket服務發送數據包
    ds.close();
   } catch (UnknownHostException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  } catch (SocketException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
}


6,udp建立接受端

   

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.Scanner;

/*
 * 需求:
 * 定義一個應用程序,用於接收ydp協議傳輸的數據並處理的
 * 思路
 * 1,定義udpsocket服務.通常會監聽一個端口,其實就是給這個接收網絡應用程序定義數字標識
 * 方便於明確,那些數據過來,該應用程序可以處理
 * 2,定義一個數據包,因爲要存儲接收到的字節數據。
 * 因爲數據包對象中有更多功能可以提取字節數據中的不同數據信息
 * 3,通過socket服務receive方法將收到的數據存入已定義好的數據包。
 * 4,通過數據包對象的特有功能。講這些不同的數據取出,打印在控制檯上。
 * 5,關閉資源
 *
 */
public class UdpRe {
 public static void main(String[] args) {
  DatagramSocket ds = null;
  try {
   // 1建立udp socket,建立端點
   ds = new DatagramSocket(1000);// 系統可以分配
   // 2定義數據包,
   byte[] b = new byte[1024];
   DatagramPacket dp = new DatagramPacket(b, b.length);
   // 3通過服務的receive方法將收到的數據存入數據包中。

   ds.receive(dp);//阻塞式方法,沒有數據就等,線程機制wait,發過來數據的時候notify喚醒
   // 4,通過數據包的方法獲取其中的數據
   String ip = dp.getAddress().getHostAddress();
   String data = new String(dp.getData(), 0, b.length);
   int post = dp.getPort();
   System.out.println(ip + "::" + data + "::" + post);

  } catch (SocketException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } finally {

   ds.close();
  }
 }
}


 

 7 ,udp簡單聊天程序

        

/*
 * 聊天程序
 * 有接受數據的部分和發數據的部分
 * 並且同時執行
 * 多線程技術
 * 因爲收數據和發數據是不一致的,所有要定義兩個run方法,所以要有兩個類
 */
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

public class Test9 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			DatagramSocket sendsocket = new DatagramSocket();//發送端
			DatagramSocket recesocket = new DatagramSocket(10001);//接受端必須制定端口號
			Thread t1 = new Thread(new Send(sendsocket));//發送端線程
			Thread t2 = new Thread(new Rece(recesocket));//接收端 線程
			t1.start();
			t2.start();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

/*
 * 發送端類
 * 
 * @author Administrator
 */
class Send implements Runnable {
	private DatagramSocket ds;//udpsocket服務

	public Send(DatagramSocket ds) {// 初始化一個發送端DatagramSocket對象
		this.ds = ds;
	}
    //重寫run方法,鍵盤錄入io操作
	public void run() {
		// TODO Auto-generated method stub
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));// 鍵盤錄入
		try {
			String line = null;
			while ((line = br.readLine()) != null) {// 循環讀取
				if (line.equals("86"))//自定義結束標記
					
					break;
				// 構造數據包,封裝了數據,接受ip,接受端口,存儲數據
				byte[] b = line.getBytes();

				DatagramPacket dp = new DatagramPacket(b, b.length, InetAddress
						.getByName("192.168.1.100"), 10001);//封裝數據包
				ds.send(dp);//發送
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			try {
				throw new Exception("發送端失敗");
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		} finally {
			ds.close();//關閉資源
		}
	}

}

/*
 * 接收 發送端類
 * 
 * @author Administrator
 */
class Rece implements Runnable {
	private DatagramSocket ds;

	public Rece(DatagramSocket ds) {// 初始化一個接受端DatagramSocket對象,接受數據 必須明確一個端口號
		this.ds = ds;
	}

	@Override
	public void run() {// 重寫線程run方法
		// TODO Auto-generated method stub
		while (true) {
			byte[] b = new byte[1024];
			DatagramPacket dp = new DatagramPacket(b, b.length);//創建數據包,用於存儲接受的數據
			try {
				ds.receive(dp);// 阻塞式方法,將接受的數據存儲到數據包中
				// 通過數據包獲取ip,和轉換後的字符串
				String ip = dp.getAddress().getHostName();//通過數據包的方法解析包中的數據 
				String data = new String(dp.getData(), 0, dp.getLength());
				System.out.println("ip" + ip + "data" + data);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}



 

 8,TCP傳輸

     Socket(客戶端對象)和ServerSocket(服務端對象)

     建立客戶端和服務端

     建立連接後,通過Socket中的io流進行數據的傳輸

     關閉Socket

     同樣,客戶端與服務器端是兩個獨立的應用程序
     客戶端一建立,就要連接服務端

9,TCP建立客戶端

   

 import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

/*
 * 客戶端
 * 通過查閱socket對象,發現在該對象建立時,就可以去連接指定主機
 * 因爲tcp是面向連接的,所以在建立連接socket服務時。
 * 就要有服務端存在,並連接成功。形成通路後,在該通道進行數據的傳輸。
 * 需求;給服務端發送一個文本數據
 * 步驟
 *
 * 1,創建TCP 客戶端Socket服務,使用Socket對象。並指定要連接的主機和端口
 *  建議該對象一創建就明確目的地。要連接主機
 *  2,如果連接成功,說明數據的通道已建立
 *    該通道是Socket流,是底層的,既然是流,說明這裏既有輸入又有輸出
 *    可以通過getOutputStream(),和getInputSteam()來獲取兩個字節流
 *  3,使用輸出流。將數據寫出
 *  4,關閉資源
 */
public class TcpClient {
 public static void main(String[] args) {
  try {
   // 創建客戶端的socket服務,指定目的主機和端口
   Socket s = new Socket("192.168.1.100", 10001);
   // 爲了發送數據,應該獲取socket流中的輸出流
   OutputStream out = s.getOutputStream();
   out.write("aaa".getBytes());
   s.close();// socket關閉,流也關閉了
  } catch (UnknownHostException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
}


 

  10 ,使用TCP建立服務端

    

 import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;


public class TcpServer {
 public static void main(String[] args) {
  Socket s = null;
  ServerSocket ss = null;
  try {
   // 建立服務端的socket,並監聽一個端口
   ss = new ServerSocket(10001);
   // 通過accept方法獲取連接過來的客戶端對象
   s = ss.accept();// 阻塞式的方法
   String ip = s.getInetAddress().getHostAddress();
   System.out.println("ip:" + ip);
   // 獲取客戶端發送過來的數據,那麼要使用客戶端對象的讀取流方法來讀取數據
   InputStream in = s.getInputStream();
   byte[] buf = new byte[1024];
   System.out.println(new String(buf, 0, buf.length));
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } finally {
   try {
    s.close();
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }// 不關自己,關閉客戶端
   try {
    ss.close();
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
 }
}


 

 11,使用tcp建立交互方式

客戶端

  

 import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

 /*
 * 客服端
 * 1,建立socket服務指定要連接主機和端口子
 * 2,獲取socket流中的輸出流,將數據寫到該流中,通過網絡發送給服務端
 *
 */
public class TcpClient {
 public static void main(String[] args) {
  try {
   Socket s = new Socket("192.168.1.240", 10002);
   OutputStream out = s.getOutputStream();
   out.write("服務端,你好".getBytes());
   InputStream in = s.getInputStream();
   byte[] buf = new byte[1024];
   int len = in.read();
   System.out.println(new String(buf, 0, len));
   s.close();
  } catch (UnknownHostException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
}


 

 服務端

 import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TcpServer {
 public static void main(String[] args) {
  // 服務端接受客戶端發送過來的數據,並打印在控制檯上
  /*
   * 通過tcp服務的思路 1,建立服務端socket服務。通過ServerSocket對象 2,服務端必須對外提供一個藉口,否則客戶端無法連接
   * 3,獲取鏈接過來的客戶端對象 4,通過客戶端對象獲取socket流讀取客戶端發來的數據 並打印在控制檯上 5,關閉資源,管客戶端,管服務端
   */
  try {
   // 1創建服務端對象
   ServerSocket ss = new ServerSocket(10002);
   // 獲取連接過來的客戶端對象
   Socket s = ss.accept();
   // 2獲取ip
   String ip = s.getInetAddress().getHostAddress();
   System.out.println("ip:" + ip);
   // 通過socket對象獲取輸入流,要對客戶端發過來的數據
   InputStream in = s.getInputStream();
   byte[] buf = new byte[1024];
   int len = in.read(buf);
   System.out.println(new String(buf, 0, len));
   // 使用客戶端socket對象的輸出流給客戶端返回數據
   OutputStream out = s.getOutputStream();
   out.write("收到".getBytes());
   s.close();
   ss.close();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
}



客戶端上傳圖片

單人

 

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

/*
 * 單人上傳圖片
 * 客戶端。
 * 1,服務端點
 * 2,去讀客戶端已有的圖片數據
 * 3,通過socket輸出流將數據發送給服務端
 * 4,讀取服務端反饋信息
 * 5,關閉
 */
public class PicClient {
	public static void main(String[] args) throws Exception, IOException {
		Socket s = new Socket("192.168.1.100", 10004);
		FileInputStream fis = new FileInputStream("c:\\1.jpg");
		OutputStream out = s.getOutputStream();
		byte[] buf = new byte[1024];
		int len = 0;
		while ((len = fis.read(buf)) != -1) {
			out.write(buf, 0, len);
		}
		// 告訴服務端數據已寫完
		s.shutdownOutput();
		InputStream in = s.getInputStream();
		byte[] bufin = new byte[1024];
		int num = in.read(bufin);
		System.out.println(new String(bufin, 0, num));
		fis.close();
		s.close();
	}

}

class PicServer {
	public static void main(String[] args) throws Exception {
		ServerSocket ss = new ServerSocket(10004);
		Socket s = ss.accept();
		InputStream in = s.getInputStream();
		FileOutputStream fos = new FileOutputStream("c:\\server.jpg");
		byte[] buf = new byte[1024];
		int len = 0;
		while ((len = in.read(buf)) != -1) {
			fos.write(buf, 0, len);
		}
		OutputStream out = s.getOutputStream();
		out.write("上傳成功".getBytes());
		fos.close();
		s.close();
		ss.close();
	}
}

客戶端併發上傳圖片

 加上while的方案

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

/*
 * 單人上傳圖片
 * 客戶端。
 * 1,服務端點
 * 2,去讀客戶端已有的圖片數據
 * 3,通過socket輸出流將數據發送給服務端
 * 4,讀取服務端反饋信息
 * 5,關閉
 */
public class PicClient {
	public static void main(String[] args) throws Exception, IOException {
		Socket s = new Socket("192.168.1.100", 10004);
		FileInputStream fis = new FileInputStream("c:\\1.jpg");
		OutputStream out = s.getOutputStream();
		byte[] buf = new byte[1024];
		int len = 0;
		while ((len = fis.read(buf)) != -1) {
			out.write(buf, 0, len);
		}
		// 告訴服務端數據已寫完
		s.shutdownOutput();
		InputStream in = s.getInputStream();
		byte[] bufin = new byte[1024];
		int num = in.read(bufin);
		System.out.println(new String(bufin, 0, num));
		fis.close();
		s.close();
	}

}

class PicServer {
	public static void main(String[] args) throws Exception {
		ServerSocket ss = new ServerSocket(10004);
			while(true){
			Socket s = ss.accept();
			InputStream in = s.getInputStream();
			FileOutputStream fos = new FileOutputStream("c:\\server.jpg");
			byte[] buf = new byte[1024];
			int len = 0;
			while ((len = in.read(buf)) != -1) {
				fos.write(buf, 0, len);
			}
			OutputStream out = s.getOutputStream();
			out.write("上傳成功".getBytes());
			fos.close();
			s.close();
			ss.close();
		}
	}
}



這個服務端有個侷限性。當a客戶端連接上以後,被服務端獲取到,服務端執行具體執行流程,

這時b客戶端連接,只有等待

因爲服務端還沒有處理完A客戶端的請求,還沒有循環回來執行accept方法。所以暫時獲取不到B客戶對象。

那麼爲了可以讓多個客戶端同時併發訪問服務

那麼服務端最好就是將每個客戶端封裝到一個單獨的線程中。這樣,就可以同屬處理多個客戶端請求。

如何定義線程呢?

只要明確了每一個客戶端要在服務端執行的代碼即可。將該代碼存入run方法中。

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
public class PicClient {
	public static void main(String[] args) throws Exception, IOException {
		// 主函數傳值
		if (args.length != 1) {
			System.out.println("請選擇一個jpd格式的圖片");
			return;
		}
		File file = new File(args[0]);//根據傳入的值,實例file對象
		if (!(file.exists() && file.isFile())) {//判斷是否存在,是不是文件
			System.out.println("該文件有問題,要麼不存在,要麼不是文件");
			return;
		}
		if (!(file.getName().endsWith(".jpg"))) {//判斷是不是以.jpg爲後綴的
			System.out.println("圖片格式錯誤,請重新選擇");
			return;
		}
		if (file.length() > 1024 * 1024 * 5) {//對文件的大小進行設置
			System.out.println("文件過大");
			return;
		}
		Socket s = new Socket("192.168.1.100", 10004);//指定ip和端口號
		FileInputStream fis = new FileInputStream("c:\\1.jpg");//得到文件輸入流,根據文件所在的路徑
		OutputStream out = s.getOutputStream();//得到輸出流
		byte[] buf = new byte[1024];
		int len = 0;
		while ((len = fis.read(buf)) != -1) {//把文件寫入指定的流中。上傳到客戶端
			out.write(buf, 0, len);
		}
		// 告訴服務端數據已寫完
		s.shutdownOutput();
		InputStream in = s.getInputStream();//得到服務端的反饋信息
		byte[] bufin = new byte[1024];//緩衝數組
		int num = in.read(bufin);//讀取的字節數
		System.out.println(new String(bufin, 0, num));//打印輸出
		fis.close();
		s.close();
	}

}

class PicServer {
	public static void main(String[] args) throws Exception {
		ServerSocket ss = new ServerSocket(10004);//服務端Socket指定端口
		while (true) {
			Socket s = ss.accept();//阻塞式接受
			new Thread(new PicThread(s)).start();//線程開啓,多線程,併發上傳
		}

	}
}

class PicThread implements Runnable {
	private Socket s;

	PicThread(Socket s) {
		this.s = s;
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		int count = 1;// 如果定義到成員,多個線程共享數據了。不安全
		String ip = s.getInetAddress().getHostAddress();
		try {
			System.out.println(ip + "...connected");
			InputStream in = s.getInputStream();
			// 爲了不覆蓋,用ip地址來命名
			File file = new File(ip + "(" + (count) + ")" + ".jpg");
			while (file.exists()) {//判斷文件是否存在
				file = new File(ip + "(" + (count++) + ")" + ".jpg");
			}
			FileOutputStream fos = new FileOutputStream(file);//文件輸出流
			byte[] buf = new byte[1024];
			int len = 0;
			while ((len = in.read(buf)) != -1) {
				fos.write(buf, 0, len);
			}
			OutputStream out = s.getOutputStream();
			out.write("上傳成功".getBytes());//返回給客戶端的信息
			fos.close();
			s.close();
		} catch (Exception e) {
			throw new RuntimeException(ip + "上傳失敗");
		}
	}

}



 客戶端併發登陸

 客戶端

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

/*
 *客戶端通過鍵盤錄入用戶名。
 *服務端對這個用戶名進行校驗。
 *如果該用戶名存在,在服務端系那是xxx,已登錄
 *並在客戶端顯示xxx歡迎光臨。
 *如果該用戶不存在在服務端顯示xxx,嘗試登陸。
 *並在客戶端顯示xxx,該用戶不存在。
 *最多就登陸三次 
 *
 */
public class LoginClient{
   public static void main(String[] args) throws Exception, IOException {
	 Socket s=new Socket("192.168.1.100",10006);
	 BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
	 PrintWriter out=new PrintWriter(s.getOutputStream(),true);
	 BufferedReader bufin=new BufferedReader(new InputStreamReader(s.getInputStream()));
	 for(int x=0;x<3;x++){
		 String line=bufr.readLine();//讀一次
          if(line==null){
        	  break;
          }
		 out.println(line);//發出去
		 String info=bufin.readLine();//讀取服務端的反饋信息
		
		 System.out.println("info:"+info);//打印反饋信息
		 if(info.contains("歡迎")){
				break;
			}
	 }
	 bufr.close();
	 s.close();
  }
}


服務端

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;


public class LoinServer {
    public static void main(String[] args) throws Exception {
		ServerSocket ss=new ServerSocket(10006);
		while(true){
			Socket s=ss.accept();
			new Thread(new UserThread(s)).start();
		}
	} 
}
class UserThread implements Runnable{
	private Socket s;
	UserThread(Socket s){
		this.s=s;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		String ip=s.getInetAddress().getHostAddress();
		System.out.println(ip+"...connected");
		try{
			for(int x=0;x<3;x++){
				BufferedReader bufin=new BufferedReader(new InputStreamReader(s.getInputStream()));
				String name=bufin.readLine();
				if(name==null){//客戶端ctrl+c停止了
					break;
				}
				BufferedReader bufr=new BufferedReader(new FileReader("c:\\user.txt"));
				PrintWriter out=new PrintWriter(s.getOutputStream());
				String line=null;
				boolean flag=false;
				while((line=bufr.readLine())!=null){
					if(line.equals(name) ){
						flag=true;
						break;
					}
				}
				if(flag){
					System.out.println(name+",已登錄");
					out.println(name+",歡迎光臨");
					break;
				}else{
					System.out.println(name+",嘗試登陸");
					out.println(name+",用戶名不存在");
				
				}
			}
			s.close();
		}catch(Exception ex){
			throw new RuntimeException(ip+"校驗失敗");
		}
	}
}


 瀏覽器客戶端-自定義服務端

import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

/*
 * 演示客戶端和服務端
 * 1,客戶端:瀏覽器
 * 2,服務端,自定義
 */
public class ServerDemo {
	public static void main(String[] args) throws Exception {
		ServerSocket ss = new ServerSocket(11000);
		Socket s = ss.accept();
		System.out.println(s.getInetAddress().getHostAddress());
		PrintWriter out = new PrintWriter(s.getOutputStream(), true);
		out.println("客戶端你好");
		s.close();
		ss.close();
	}
}


如上圖所示客戶端

瀏覽器客戶端-Tomcat服務端

在tomcat下的webapps下面新建myweb 裏面有一個demo.html文件訪問成功如下圖

 

自定義瀏覽器-Tomcat服務端

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

/*
 *模擬瀏覽器的動作,向tomcat服務請求數據
 *瀏覽器在訪問服務器中到底發送了什麼數據?才能請求道myweb資源呢?
 */
public class ServerDemo {
	public static void main(String[] args) throws Exception {
		ServerSocket ss = new ServerSocket(11000);
		Socket s = ss.accept();
		System.out.println(s.getInetAddress().getHostAddress());
		InputStream in=s.getInputStream();
		byte []buf=new byte[1024];
		int len=in.read(buf);
		System.out.println(new String(buf,0,len));
		PrintWriter out = new PrintWriter(s.getOutputStream(), true);
		out.println("客戶端你好");
		s.close();
		ss.close();
	}
}

客戶端沒有變化,服務端打印出了一些數據,這些數據到底是什麼呢?

 /* 192.168.1.100
GET / HTTP/1.1
Accept: */*
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; CIBA; .NET4.0C; .NET4.0E; InfoPath.2)
Accept-Encoding: gzip, deflate
Host: 192.168.1.100:11000
Connection: Keep-Alive*/下面還有一行叫做請求數據體
瀏覽器給服務端發送了這些消息,這些就是Http請求消息頭。瀏覽器和tomcat服務器雖然是不同廠商製作的客戶端和服務端,但是他們都遵從了一些國際標準化的協議規則,在底層都走的tcp,在應用層http協議,公共的傳輸規則。瀏覽器廠商要想和不同廠商的服務器進行數據交互的話,他們必須得遵守規則。
自定義客戶端  服務端 tomcat

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

/*
 *自定義客戶端
 *服務端 tomcat 
 *
 */
public class MyIE {
   public static void main(String[] args) throws Exception, IOException {
       Socket s=new Socket("192.168.1.100",8080);	
       PrintWriter out=new PrintWriter(s.getOutputStream(),true);
       out.println("GET /myweb/demo.html HTTP/1.1");
       out.println("Accept: */*");//什麼都支持
       out.println("Accept-Language: zh-CN");//支持簡體中文
       out.println("Connection: Keep-Alive");//加上後變慢。
       
       out.println();//一定要寫空行,要和請求體分開。
       out.println();  //一定要寫空行
       //服務端要發數據到本瀏覽器中。
       BufferedReader bufr=new BufferedReader(new InputStreamReader(s.getInputStream()));
       String line=null;
       while((line=bufr.readLine())!=null){
    	   System.out.println(line);
       }
       s.close();
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章