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]