网络通信传输
1.涉及一个知识,OSI的七层模型,和TCP/IP四层模型。
各个层之间所对应的协议。
2.Socket主要是用来解决网络通信的,我们来理解网络中进程是如何通信的。
在此之前,网络间进程的通信需要解决两个问题:
a.确定通信发生在哪台主机上。
b.确定主机上的哪个进程。
基于现在的解决方案是:
a.TCP/IP协议可以帮助我们,在网络层的IP地址可以帮助我们定位主机。
b.TCP协议中,根据端口区分不同的应用进程,或者说,协议+端口。
总之,协议+IP+端口可以解决网络中的进程通信
3.Socket:
它是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
socket 是处于传输层之上封装的网络接口,方便应用层、会话层等使用。socket 的本意是“插口或插槽”,顾名思义,可以将 socket 想象成一根网线,一头插在客户端,一头插在服务端,然后进行通信,故客户端与服务端在通信之前必须要创建一个 socket。
由于此 socket 对于 tcp/ip 各种协议通用,故 socket 必须提供各种选项,例如使用 IPv4 和 IPv6 分别对应选项 AF_INET 和 AF_INET6。另外,还要指定到底是 TCP 还是 UDP,由于 TCP 是基于数据流的,所以设置为 SOCK_STREAM,而 UDP 是基于数据报的,因而设置为 SOCK_DGRAM。
从上述 socket 描述中可以看出,socket 是一个端到端的通信,关于中间经过多少局域网,多少路由器,因而能够设置的参数,也只是端到端协议之上的网络层和传输层。
TCP/IP协议族包括运输层、网络层、链路层。或者理解为socket是一个接口,在用户进程与TCP/IP协议之间充当中间人,完成TCP/IP协议,用户只需理解接口即可。
IP
java中有一个类叫做,InetAddress。是用来表示Internet协议(IP)地址的一个类。里面实现一些诸如根据返回IP,返回计算机名还有其他一些的一些方法。
org.xbill.DNS.Address。这个类可以根据ip地址拿到域名,但是并没有成功执行。
import org.xbill.DNS.Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* InetAddress:常用方法
* getByName()
* getHostName()
* getLocalAddress()
*
* */
public class IPTest {
public static void main(String[] args) {
try {
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(localHost.getHostAddress());//返回IP地址
System.out.println(localHost.getHostName());//输出计算机名
//根据域名得到ip
localHost = InetAddress.getByName("www.shsxt.com");
System.out.println(localHost.getHostAddress());
System.out.println(localHost.getHostName());
//根据ip得到域名,此方法暂不可用。
String hostName = Address.getHostName(InetAddress.getByName("123.56.138.186"));
} catch (UnknownHostException e) {
e.getStackTrace();
}
}
}
端口
InetSocketAddress类。
/**
* InetSocketAddress 区分软件、端口
*
* 端口:
* 端口区分不同软件
* 2个字节组成,o-65535
* 同一协议下,端口不可以冲突,不同协议下也不建议相同,便于区分
* 定义端口需注意,已经使用的端口
*
* InetSocketAddress:
* 封装端口与ip地址的一个类
* 常用方法:getAddress(),getPort(),getHostName()
*
* */
import java.net.InetSocketAddress;
public class PortTest {
public static void main(String[] args) {
InetSocketAddress isa = new InetSocketAddress("localhost",8080);
//一些方法,可以得到参数信息
System.out.println(isa.getAddress());
System.out.println(isa.getHostName());
System.out.println(isa.getHostString());
System.out.println(isa.getPort());
}
}
URL
1.利用url去爬网站的源码
InputStream is = url.openStream(); 此方法返回一个流,将流所携带的信息处理出来,既是网站的源码。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
/**
* URL,资源统一定位符。
* 常用方法。
* getProtocol(),协议类型。
* getDefaultPort(),默认端口。
* 。。。
* */
public class UrlTest {
public static void main(String[] args) {
try {
URL url = new URL("https://fanyi.baidu.com");
System.out.println("--"+url.getDefaultPort());
System.out.println("--"+url.getHost());
System.out.println("--"+url.getPort());
System.out.println("--"+url.getProtocol());
InputStream is = url.openStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is, "utf-8"));
String msg;
while(null != (msg=br.readLine())){
System.out.println(msg);
}
br.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.利用url去爬不让爬源码的网站
这里需要绕过网站的检测,让网站以为我们其实使用浏览器登录,这样就可以了。因为我们在浏览器是可以正常登录和查看源码的。
1.使用到了HttpURLConnection,使用HttpURLConnection来访问网络,首先需要获取它的实例。
它需要new 一个URL对象,HttpURLConnection connection = (HttpURLConnection) url.openConnection();
这个方法返回一个HttpURLConnection实例。之后就可以通过这个实例设置一些Http请求的属性和方法了
2.HttpURLConnection可以设置get或者post请求,然后setRequestProperty()方法里面的内容需要去浏览器拿到。在Request Headers里面的User-Agent那串内容
例如:User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36。这串内容表示了浏览器的一些信息的集合。
3.设置好了之后,可以像之前那样去网络上爬源码。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
/**
* 爬虫(不可爬的网站)
* 骗过网站的方法。
* setRequestMethod().请求方式
* setRequestProperty(String key, String value).里面填写use-agent,和它的内容。这就表示是浏览器在发出这个请求,从而骗过网站。
*
* 使用HttpURLConnection来访问网络,首先需要获取它的实例,它需要new 一个URL对象,
* 例如URL url = new URL("http://www.baidu.com") ,
* 再使用HttpURLConnection connection = (HttpURLConnection) url.openConnection();
* 这个方法返回一个HttpURLConnection实例。之后就可以通过这个实例设置一些Http请求的属性和方法了
*
* 。。。
* */
public class UrlTest02 {
public static void main(String[] args) {
try {
URL url = new URL("https://www.dianping.com");
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36");
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
String msg;
while(null != (msg=br.readLine())){
System.out.println(msg);
}
br.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}