Java 网络编程四 C/S B/S(例:模拟浏览器、服务器、网络爬虫)

C/S 与 B/S

☆ C/S ( Client/Server ) 客户端和服务端的特点

1、客户端和服务端的软件都需要程序员进行编写。
2、客户端维护起来较为麻烦。
3、客户端的存在可以将一部分运算分离到客户端来运行,减轻了服务器端的压力。

☆ B/S ( Browse/Server ) 浏览器和服务端的特点

1、客户端不用程序员编写,直接使用系统中具备的浏览器软件作为客户端即可。程序员只需要编写服务器端就OK了。
2、维护起来也很容易,因为只要维护服务器即可。
3、所有的运算都在服务器端,相对压力较大。


下面通过几个练习理解一下B/S模式的底层socket通讯原理

1、自定义一个服务器,接收浏览器发来的信息。显示浏览器发送了什么信息,并向浏览器发送简单的网页信息。

package cn.hncu.net.bs;

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


/**
 * @authordragon_Dai
 * @version 2017-8-14 下午7:27:41
 * @filename MyServer.java
 * 
 * 模拟服务器,接收浏览器发送的信息,并向浏览器返回一个简单的网页信息(还没学习html)
 */
public class MyServer {
	public static void main(String[] args) {
		ServerSocket server=null;
		try {
			server = new ServerSocket(80);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		if(server!=null){
			while(true){
				try {
					Socket s=server.accept();
					String ip=s.getInetAddress().getHostAddress();	//获取向服务器请求的ip地址
					System.out.println(ip+":请求信息");
					//获取浏览器向服务器请求的信息
	//				InputStream is=s.getInputStream();
	//				byte bs[]=new byte[512];
	//				int len=-1;
	//				while((len=is.read(bs))!=-1){
	//					System.out.print(new String(bs, 0, len));
	//				}
					
	//				BufferedReader br2=new BufferedReader(new InputStreamReader(s.getInputStream()));
	//				String str=null;
	//				while((str=br2.readLine())!=null){
	//					System.out.println(str);
	//				}
					//上面两种方法获取浏览器向服务器请求的信息的方式都是不可取的,因为无法判断结束,浏览器有它自己的判断方式。
					//只能一次性全部读取.
					
					//获取浏览器向服务器请求的信息
					byte buf[]=new byte[512];
					InputStream in = s.getInputStream();
					int len = in.read(buf);
					String txt = new String(buf,0,len);
					System.out.println(txt);
					
					//返还给浏览器信息
					//发送的请求需要浏览器认识,仍然需要采用http协议的请求头
					PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
	//				pw.println("HTTP/1.1 200 OK");//HTTTP协议中的响应行
	//				pw.println("Content-Type: text/html;charset=UTF-8");//设置编码
	//				pw.println();		//协议请求头结束之后,需要一个空行
					//上诉协议的请求头我加入到了html文件中。
					
					//接下来返还一个网页的信息(.html)
					//源:从文件中读取
					BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream("dragon.html")));
					String str2=null;
					while((str2=br.readLine())!=null){
						pw.println(str2);	//在写入到socket中
					}
					
					System.out.println("------------------------over");
					
					//关流
					in.close();
					pw.close();
					br.close();
					s.close();
					
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
dragon.html

HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8


	
		

欢迎你....

姓名 年龄
dragon 20
19

链接:我的博客
1:当使用IE浏览器 访问127.0.0.1(访问一次)时:服务器记录信息如下:

127.0.0.1:请求信息
GET / HTTP/1.1
Accept: text/html, application/xhtml+xml, image/jxr, */*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko
Accept-Encoding: gzip, deflate
Host: 127.0.0.1
DNT: 1
Connection: Keep-Alive


------------------------over
2:当使用360浏览器访问127.0.0.1(访问一次)时:服务器记录信息如下:

127.0.0.1:请求信息
GET / HTTP/1.1
Host: 127.0.0.1
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: zh-CN,zh;q=0.8
Cookie: __guid=96992031.1350441646852180200.1502715904461.7183; monitor_count=27


------------------------over
127.0.0.1:请求信息
GET /favicon.ico HTTP/1.1
Host: 127.0.0.1
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
Accept: image/webp,image/*,*/*;q=0.8
Referer: http://127.0.0.1/
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: zh-CN,zh;q=0.8
Cookie: __guid=96992031.1350441646852180200.1502715904461.7183; monitor_count=28


------------------------over
同样是访问一次,360浏览器记录2次信息。IE浏览器记录一次信息。这问题说明了不同的浏览器之间的机制不一样。

使用多线程如下:

package cn.hncu.net.bs;

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

/**
 * @authordragon_Dai
 * @version 2017-8-14 下午8:51:51
 * @filename MyServer2.java
 * 
 * 模拟服务器,接收浏览器发送的信息,并向浏览器返回一个简单的网页信息(还没学习html)
 * 多线程版本
 */
public class MyServer2 {
	public static void main(String[] args) {
		try {
			ServerSocket server=new ServerSocket(80);
			while(true){
				Socket s=server.accept();
				new Thread(new MyRun(s)).start();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
}

class MyRun implements Runnable{

	private Socket s;
	public MyRun(Socket s) {
		this.s=s;
	}

	@Override
	public void run() {
		String ip=s.getInetAddress().getHostAddress();
		System.out.println(ip+"请求信息");
		
		//获取浏览器的请求信息
		try {
//			BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
//			String str=null;
//			while((str=br.readLine())!=null){
//				System.out.println(str);
//			}
			//只能一次性把浏览器请求的信息全部获取。
			byte buf[]=new byte[512];
			InputStream in = s.getInputStream();
			int len = in.read(buf);
			String txt = new String(buf,0,len);
			System.out.println(txt);
			//返还给浏览器信息
			//发送的请求需要浏览器认识,仍然需要采用http协议的请求头
			PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
			
			//接下来返还一个网页的信息(.html)
			//源:从文件中读取
			BufferedReader br2=new BufferedReader(new InputStreamReader(new FileInputStream("dragon.html")));
			String str2=null;
			while((str2=br2.readLine())!=null){
				pw.println(str2);	//在写入到socket中
			}
			
			//关流
			in.close();
			pw.close();
			br2.close();
			s.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
}

2、模拟一个浏览器客户端向服务器发请求,接收并显示响应消息。

package cn.hncu.net.bs;

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

/**
 * @authordragon_Dai
 * @version 2017-8-14 下午6:29:21
 * @filename MyBrowse.java
 * 
 * 简单模拟一下浏览器,向服务器发送请求,并且接收来自服务器的响应信息。
 */
public class MyBrowse {
	public static void main(String[] args) {
		try {
			//浏览器为每个服务器默认添加的端口号是:80
			Socket s=new Socket("news.baidu.com", 80);
			
			//向服务器发送请求  
			PrintWriter pw=new PrintWriter(s.getOutputStream(),true);//自动刷缓存
			
			//发送的请求需要浏览器认识,所以要采用http协议的请求头
			pw.println("GET / HTTP/1.1");	//http协议中的响应行
			pw.println("Accept: text/html, application/xhtml+xml, */*");
			pw.println("Host:news.baidu.com");
			pw.println("Connection: Keep-Alive");
			pw.println();		//协议请求头结束之后需要一个空行
			
			
			//接收服务器的响应信息
			BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
			String str=null;
			while((str=br.readLine())!=null){
				System.out.println(str);
			}
			
			//关流
			pw.close();
			br.close();
			s.close();
			
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
运行结果:

HTTP/1.1 200 OK
Connection: keep-alive
Content-Type: text/html;charset=utf-8
Date: Mon, 14 Aug 2017 15:57:17 GMT
P3p: CP=" OTI DSP COR IVA OUR IND COM "
Server: Apache
Set-Cookie: BAIDUID=37A6CC4CA8CF47D6D1BB6995D029805E:FG=1; expires=Tue, 14-Aug-18 15:57:17 GMT; max-age=31536000; path=/; domain=.baidu.com; version=1
Tracecode: 34374410850742441738081423
Tracecode: 34374114540907268106081423
Vary: Accept-Encoding
Vary: Accept-Encoding
Transfer-Encoding: chunked

e1a

...
下面是网页的源代码信息
...
...
3、网络蜘蛛,收集网页中的邮箱地址信息。

package cn.hncu.net.spider;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.junit.Test;

/**
 * @authordragon_Dai
 * @version 2017-8-14 下午7:58:38
 * @filename SpiderDemo.java
 * 
 * 简单的网络爬虫(蜘蛛),爬取网页中邮箱信息
 *   没有算法。。
 */
public class SpiderDemo {
	
	//1.先在本地的一个文件中测试一下看能否爬取到邮箱地址信息
	@Test
	public void demo1(){
		try {
			BufferedReader br=new BufferedReader(new FileReader("mail.html"));
			
			//正则表达式
//			String regex="//w+@//w+(//.//w+)+";		错误
			String regex ="\\w+@\\w+(\\.\\w+)+";
			//工具
			Pattern p=Pattern.compile(regex);
			
			String str=null;
			while((str=br.readLine())!=null){
				Matcher m = p.matcher(str);		//用str去匹配 正则表达式
				while(m.find()){		//如果匹配成功
					System.out.println(m.group());	//输出匹配结果
				}
			}
			
			br.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	//2.到网络页面爬取邮箱地址
	@Test
	public void demo2(){
		try {
			URL url=new URL("http://acm.hdu.edu.cn");
			//url.openStream() 打开到此 URL 的连接并返回一个用于从该连接读入的 InputStream。
			BufferedReader br=new BufferedReader(new InputStreamReader(url.openStream()));
			
			//正则表达式
			String regex="\\w+@\\w+(\\.\\w+)+";
			
			//工具
			Pattern p=Pattern.compile(regex);
			
			String str=null;
			while((str=br.readLine())!=null){
				Matcher m=p.matcher(str);
				while(m.find()){
					System.out.println(m.group());
				}
			}
			
			//关流
			br.close();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
}
demo1:

mail.html


	
		用于演示网络爬虫的网页
	

	
			

☆ C/S ( Client/Server ) 客户端和服务端的特点 1、客户端和服务端的软件都需要程序员进行编写。 2、客户端维护起来较为麻烦。(缺陷) 3、客户端的存在可以将一部分运算分离到客户端来运行,减轻了服务器端的压力。(优势) ☆ B/S ( Browse/Server ) 浏览器和服务端的特点 1、客户端不用程序员编写,直接使用系统中具备的浏览器软件作为客户端即可。程序员只需要编写服务器端就OK了。 2、维护起来也很容易,因为只要维护服务器即可。(优势) 3、所有的运算都在服务器端,相对压力较大。(缺陷)

[email protected]
姓名:
联系站长
爬取结果:

[email protected]
[email protected]
[email protected]
demo2:

爬取结果:

[email protected]
[email protected]
[email protected]
[email protected]

你可能感兴趣的:(----java,net,网络编程-----)