Java网络编程
一、概念
IP地址:确定计算机在网络上的哪个节点
端口号:确定app和哪个服务器对接,区分计算机上的软件,相当于一个房门。ex: QQ - 对接QQ的sever。2个字节,范围 0 - 65536
- 同一协议下,端口号不能重复
- 1024以下的端口不要使用,0-1024是给某些厂商预留的端口。ex: 80--> http , 21 ---> ftp
确定了地址(计算机),确定了端口(软件),接下来还需要确定资源怎么进来。
资源定位符: URL (既有资源又有定位), URI (资源)
数据传输: 比如确定用什么语言啊之类的,所以需要有协议
- TCP协议(transfer control protocol)(必须先连接,类似于打电话),需要三次握手,所以安全,但是效率低下 / 面向连接
- UDP协议 (user datagram protocol)(类似于发短信,只管往外发),不需要先连接,所以不安全,但效率高 /非面向连接
传输:先封装,后拆封,这样就涉及到了网络分层
网络分层
- 应用层
- 传输层(TCP/UDP)
- 网络层(IP)
- 物理 + 数据链路层
涉及到的java类
- IP:InetAddress , 端口:InetSocketAddress
- URL
- TCP: ServerSocket, Socket
- UDP: DatagramSocket, DatagramPacket
二、InetAddress 和 InetSocketAddress
InetAddress: 封装了IP地址和DNS(域名解析),但没有端口。 域名解析: 比如把 223.87.1.58解析为www.163.com (你记不住有的没的一串数字的)
InetSocketAddress: 包含端口
InetAddress方法:
- getHostAddress() //返回IP地址
- getHostName() //返回域名,本机为计算机名
- getLocalHost()
- getByName(“IP地址 / 或者域名”)
InetSocketAddress封装端口
1、创建对象
2、方法
- getAddress()
- getHostName()
- getPort()
三、URL, 网络爬虫原理
URL/URI,统一资源定位符,有4部分组成:
- 协议
- 存放资源的主机域名
- 端口
- 资源文件名
URL (String spec) //绝对路径构建
URL(URL context, String spec) //相对路劲构建
public class URLDemo {
public static void main(String[] args) throws MalformedURLException {
//绝对路径
URL url = new URL("http://www.baidu.com:80/index.html#aa?uname=maxmaxmax");
//方法
System.out.println("协议: " + url.getProtocol() );
System.out.println("域名: " + url.getHost() );
System.out.println("端口: " + url.getPort() );
System.out.println("资源: " + url.getFile() );
System.out.println("相对路径: " + url.getPath() );
System.out.println("锚点: " + url.getRef() );
System.out.println("参数 " + url.getQuery() ); //?参数:存在锚点,返回Null,不存在,返回正确
//相对路径
URL url2 = new URL("http://www.baidu.com:80/a/");
URL url3= new URL(url2, "b.txt");
}
}
/***
* 获取资源:源代码 (通过流)
*/
public class URLDemo2 {
public static void main(String[] args) throws IOException {
URL url = new URL("http://www.baidu.com"); //主页,默认资源
//获取资源,右键百度首页 - 查看页面源代码 - 这里面的代码主要包含:html, css, js
//使用流获取源代码
BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream(),"utf-8"));
//把读取到的源代码输出成一个html文件
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("baidu.html"),"utf-8"));
String msg = null;
while ((msg = br.readLine())!= null){
bw.append(msg);
bw.newLine();
}
bw.flush();
bw.close();
br.close();
}
//以上其实就是网络爬虫的第一步,获取源代码,再用正则表达式分析源码,达到下载目标数据的目的,网络爬虫就是下载数据
}
四、UDP编程
创建服务器和客户端,发送数据
/**
* 服务端
* 1、创建服务器 + 端口
* 2、准备接收容器
* 3、封装成包
* 4、接收数据
* 5、分析数据
*/
public class UDP_TestDemo_MyServer {
public static void main(String[] args) throws IOException {
// 1、创建服务器 + 端口
DatagramSocket server = new DatagramSocket(8888);
// 2、准备接收容器
byte [] container = new byte[1024];
// 3、封装成包
DatagramPacket packet = new DatagramPacket(container, container.length);
// 4、接收数据
server.receive(packet);
// 5、分析数据
byte[] data = packet.getData();
int len = packet.getLength();
System.out.println(new String(data, 0, len));
// 6、释放资源
server.close();
}
}
/**
* 客户端
* 1、创建客户端 + 端口
* 2、准备数据
* 3、打包 (数据发往的地点和端口)
* 4、发送
* 5、释放
*/
public class UDP_TestDemo_MyClient {
public static void main(String[] args) throws IOException {
// 1、创建客户端 + 端口
DatagramSocket client = new DatagramSocket(6666);
// 2、准备数据
String msg = "UDP编程";
byte[] data = msg.getBytes();
// 3、 打包 (数据发往的地点和端口)
DatagramPacket packet = new DatagramPacket(data, data.length, new InetSocketAddress("LocalHost", 8888));
// 4、发送
client.send(packet);
// 5、释放
client.close();
}
}
五、TCP编程,Socket通信
区别于UDP, TCP需要先握手(确认连接),再传输数据
public class TCP_TestDemo_Server {
public static void main(String[] args) throws IOException {
// 1、创建服务器 + 指定端口
ServerSocket server = new ServerSocket(8888);
// 2、接收客户端连接,阻塞式
Socket socket = server.accept();
System.out.println("一个客户端建立连接");
// 3、发送数据
String msg = "欢迎使用";
//输出流
BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(
socket.getOutputStream()));
bw.write(msg);
bw.newLine();
bw.flush();
}
}
public class TCP_TestDemo_Client {
public static void main(String[] args) throws IOException {
// 1、创建客户端,必须指定服务器 + 端口,此时就在连接
Socket client = new Socket("localhost", 8888);
// 2、接受数据
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
String echo = br.readLine(); //看服务端的代码,有一个bw.newine(),因为br是逐行读取,不写一个newLine()的话,会读不到数据
System.out.println(echo);
}
}
上面这段代码,是一次简单的服务器和客户端的交互,只能执行一次(先运行服务端,再运行客户端),实际中,客户端可以和服务器多次交互,可以参考聊天室项目的代码。
浙公网安备 33010602011771号