一、常用类操作
(一)ip地址
定义:
用来标识网络中一个通信实体的地址。通信实体可以是计算机、路由器等。
IP地址分类:
- IPV4:32位地址,以点分十进制表示,如:192.168.0.2
- IPV6:128位,写成8个16位的无符号整数,每个整数用4个16进制表示,数之间用冒号隔开,如:3ffe:3201:1401:1280:c8ff:fe4d:db39:1984
特殊IP:
127.0.0.1是本机地址
192.168.0.0–192.168.255.255私有地址,属于非注册地址,专门为组织机构内部使用。
方法InetAddress:
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* InetAddress: 多个静态方法
* 1、getLocalHost:本机
* 2、getByName:根据域名DNS | IP地址 -->IP
*
* 两个成员方法
* 1、getHostAddress: 返回地址
* 2、getHostName:返回计算机名
*/
public class IPTest {
public static void main(String[] args) throws UnknownHostException {
//使用getLocalHost方法创建InetAddress对象 本机
InetAddress addr = InetAddress.getLocalHost();
System.out.println(addr.getHostAddress()); //返回:192.168.1.110
System.out.println(addr.getHostName()); //输出计算机名
//根据域名得到InetAddress对象
addr = InetAddress.getByName("www.shsxt.com");
System.out.println(addr.getHostAddress()); //返回 shsxt服务器的ip:
System.out.println(addr.getHostName()); //输出:www.shsxt.com
//根据ip得到InetAddress对象
addr = InetAddress.getByName("123.56.138.176");
System.out.println(addr.getHostAddress()); //返回 shsxt的ip:123.56.138.176
System.out.println(addr.getHostName()); //输出ip而不是域名。如果这个IP地 址不存在或DNS服务器不允许进行IP地址和域名的映射,
}
}
(二)端口
定义:
IP地址是用来标识一台计算机,但一台计算机上可能提供多个网络应用程序,如何来区分这些不同的程序呢?这就要用到端口。
端口是虚拟的,通过端口,一个主机上可以运行多个网络应用程序。
端口表示是16位的2进制,2个字节,0-65535,UDP、TCP两种协议,同一协议端口不能冲突
每个网络应用程序都有自己的端口
- 公认端口:0-1023 如:80端口分配给http协议,21端口分配给FTP
- 注册端口:1024-49151分配用用户进程或应用程序
- 动态/私有端口:49152-65535
- 查看所有端口号:netstat -ano
- 查看指定端口号:netstat -ano|findstr “808”
- 查看指定进程:tasklist|findstr “808”
- 查看具体程序:使用任务管理器查看PID
方法InetSocketAddress
import java.net.InetSocketAddress;
/**
* InetSocketAddress
* 1、构造器
* new InetSocketAddress(地址|域名,端口);
* 2、方法
* getAddress()
* getPort()
* getHostName()
*/
public class PortTest {
public static void main(String[] args) {
//包含端口
InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1",8080);
InetSocketAddress socketAddress2 = new InetSocketAddress("localhost",9000);
System.out.println(socketAddress.getHostName());
System.out.println(socketAddress.getAddress());
System.out.println(socketAddress2.getAddress());
System.out.println(socketAddress2.getPort());
}
}
(三)URL
定义:
同一资源定位符,由四部分组成:协议、存放资源的主机名、端口号、资源文件名。
方法URL
import java.net.MalformedURLException;
import java.net.URL;
/**
* URL: 统一资源定位器,互联网三大基石之一(html http),区分资源
* 1、协议
* 2、域名、计算机
* 3、端口: 默认80
* 4、请求资源
* http://www.baidu.com:80/index.html?uname=shsxt&age=18#a
*/
public class URLTest01 {
public static void main(String[] args) throws MalformedURLException {
URL url = new URL("http://www.baidu.com:80/index.html?uname=shsxt&age=18#a");
//获取四个值
System.out.println("协议:"+url.getProtocol());
System.out.println("域名|ip:"+url.getHost());
System.out.println("端口:"+url.getPort());
System.out.println("请求资源1:"+url.getFile());
System.out.println("请求资源2:"+url.getPath());
//参数
System.out.println("参数:"+url.getQuery());
//锚点
System.out.println("锚点:"+url.getRef());
}
}
模拟网络爬虫
案例1:
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
public class SpiderTest01 {
public static void main(String[] args) throws Exception {
//获取URL
URL url =new URL("https://www.jd.com");
//下载资源
InputStream is = url.openStream();
BufferedReader br =new BufferedReader(new InputStreamReader(is,"UTF-8"));
String msg =null;
while(null!=(msg=br.readLine())) {
System.out.println(msg);
}
br.close();
//分析
//处理。。。。
}
}
案例2:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* 网络爬虫的原理 +模拟浏览器
*/
public class SpiderTest02 {
public static void main(String[] args) throws Exception {
//获取URL
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; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36");
BufferedReader br =new BufferedReader(new InputStreamReader(conn.getInputStream(),"UTF-8"));
String msg =null;
while(null!=(msg=br.readLine())) {
System.out.println(msg);
}
br.close();
//分析
//处理。。。。
}
}
二、TCP编程
补充套接字
我们开发的网络应用程序位于应用层,TCP和UDP属于传输层协议,在应用层如何使用传输层的服务呢?在应用层和传输层之间则是使用套接字来进行分离,它就像传输层为应用层开的一个小口
TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议。
特点:
- 面向连接
- 点到点的通信
- 高可靠性
- 占用系统资源多,效率低
- TCP协议基于请求——响应模式
- 在网络通讯中,第一次主动发起通讯的程序被称作客户端程序
- 在一次通讯中等待连接的程序被称作服务器端程序
- 利用IO流实现数据传输
详细步骤:
案例1
服务器
import java.io.DataInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 熟悉流程
* 创建服务器
* 1.指定端口:使用ServerSocket创建服务器
* 2.阻塞式等待连接accept
* 3.操作:输入输出操作
* 4.释放资源
*/
public class Server {
public static void main(String[] args) throws IOException {
//1.指定端口:使用ServerSocket创建服务器
ServerSocket server=new ServerSocket(8888);
// 2.阻塞式等待连接accept
Socket client=server.accept();
System.out.println("一个客户端建立了连接!");
// 3.操作:输入输出操作
DataInputStream dis=new DataInputStream(client.getInputStream());
String data=dis.readUTF();
System.out.println(data);
// 4.释放资源
dis.close();
client.close();
}
}
服务器
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
/**
* 熟悉流程
* 创建客户端
* 1.建立连接:使用Socket创建客户端+服务的地址和端口
* 2.操作:输入输出操作
* 3.释放资源
*/
public class Client {
public static void main(String[] args) throws IOException {
//1.建立连接:使用Socket创建客户端+服务的地址和端口
Socket client=new Socket("localhost",8888);
//2.操作:输入输出操作
DataOutputStream dos=new DataOutputStream(client.getOutputStream());
String data="hello";
dos.writeUTF(data);
dos.flush();
//3.释放资源
dos.close();
client.close();
}
}
案例2:服务器接收多个客户端的请求,并给出反馈
服务器
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 模拟登录 多个客户端请求
* 创建服务器
* 1、指定端口 使用ServerSocket创建服务器
* 2、阻塞式等待连接 accept
* 3、操作: 输入输出流操作
* 4、释放资源
*/
public class LoginMultiServer {
public static void main(String[] args) throws IOException {
System.out.println("-----Server-----");
// 1、指定端口 使用ServerSocket创建服务器
ServerSocket server =new ServerSocket(8888);
boolean isRunning =true;;
// 2、阻塞式等待连接 accept
while(isRunning) {
Socket client =server.accept();
System.out.println("一个客户端建立了连接");
new Thread(new Channel(client)).start();
}
server.close();
}
//一个channel就代表一个客户端
static class Channel implements Runnable{
private Socket client;
//输入流
private DataInputStream dis;
//输出流
private DataOutputStream dos;
public Channel(Socket client) {
this.client = client;
try {
//输入
dis = new DataInputStream(client.getInputStream());
//输出
dos =new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
release();
}
}
//接收数据
private String receive() {
String datas ="";
try {
datas = dis.readUTF();
} catch (IOException e) {
e.printStackTrace();
}
return datas;
}
//释放资源
private void release() {
// 4、释放资源
try {
if(null != dos) {
dos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(null != dis) {
dis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(null != client) {
client.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//发送数据
private void send(String msg) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
// 3、操作: 输入输出流操作
String uname ="";
String upwd ="";
//分析
String[] dataArray = receive().split("&");
for(String info:dataArray) {
String[] userInfo =info.split("=");
if(userInfo[0].equals("uname")) {
System.out.println("你的用户名为:"+userInfo[1]);
uname = userInfo[1];
}else if(userInfo[0].equals("upwd")) {
System.out.println("你的密码为:"+userInfo[1]);
upwd = userInfo[1];
}
}
if(uname.equals("shsxt") && upwd.equals("laopei")) { //成功
send("登录成功,欢迎回来");
}else { //失败
send("用户名或密码错误");
}
release();
}
}
}
客户端
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 模拟登录 多个客户端请求
* 创建客户端
* 1、建立连接: 使用Socket创建客户端 +服务的地址和端口
* 2、操作: 输入输出流操作
* 3、释放资源
*/
public class LoginMultiClient {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("-----Client-----");
//1、建立连接: 使用Socket创建客户端 +服务的地址和端口
Socket client =new Socket("localhost",8888);
//2、操作: 输入输出流操作 先请求后响应
new Send(client).send();
new Receive(client).receive();
client.close();
}
//发送
static class Send{
private Socket client;
private DataOutputStream dos;
private BufferedReader console ;
private String msg;
public Send(Socket client) {
console=new BufferedReader(new InputStreamReader(System.in));
this.msg =init();
this.client = client;
try {
dos=new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
private String init() {
try {
System.out.print("请输入用户名:");
String uname =console.readLine();
System.out.print("请输入密码:");
String upwd =console.readLine();
return "uname="+uname+"&"+"upwd="+upwd;
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
public void send() {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//接收
static class Receive{
private Socket client;
private DataInputStream dis;
public Receive(Socket client) {
this.client = client;
try {
dis=new DataInputStream(client.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
public void receive() {
String result;
try {
result = dis.readUTF();
System.out.println(result);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
三、UDP编程
UDP是一种无连接的传输层协议,提供面向事务的简单不可靠信息传输服务。
特点:
- 非面向连接,传输不可靠,可能丢失
- 发送方不管对方是否准备好,接收方收到也不确认
- 可以广播发送
- 非常简单的协议,开销小
案例1:简单的发送接收
发送端
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
/**
* 发送端
* 1.使用DatagramSocket 指定端口 创建发送端
* 2.准备数据 一定转成字节数组
* 3.封装成DatagramPacket 包裹,需要指定目的地
* 4.发送包裹send(DatagramPacket p)
* 5.释放资源
*/
public class UdpClient {
public static void main(String[] args) throws Exception {
System.out.println("发送方启动中......");
//1.使用DatagramSocket 指定端口 创建发送端
DatagramSocket client=new DatagramSocket(8888);
//2.准备数据 一定转成字节数组
String data="你今天真好看";
byte[] datas=data.getBytes();
//3.封装成DatagramPacket 包裹,需要指定目的地
DatagramPacket packet=new DatagramPacket(datas,0,datas.length,
new InetSocketAddress("localhost",9999));
//4.发送包裹send(DatagramPacket p)
client.send(packet);
//5.释放资源
client.close();
}
}
接收端
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* 接收端
* 1.使用DatagramSocket 指定端口 创建接收端
* 2.准备容器 封装成DatagramPacket 包裹
* 3.阻塞式接收包裹receive(DatagramPacket p)
* 4.分析数据
* byte[] getData()
* getLength()
* 5.释放资源
*/
public class UdpServer {
public static void main(String[] args) throws Exception {
System.out.println("接收方启动中......");
//1.使用DatagramSocket 指定端口 创建接收端
DatagramSocket server=new DatagramSocket(9999);
//2.准备容器 封装成DatagramPacket 包裹
byte[] container=new byte[1024*60];
DatagramPacket packet=new DatagramPacket(container,0,container.length);
//3.阻塞式接收包裹receive(DatagramPacket p)
server.receive(packet);
//4.分析数据
// byte[] getData()
// getLength()
byte[] datas=packet.getData();
int len=packet.getLength();
//5.释放资源
System.out.println(new String(datas,0,len));
server.close();
}
}
案例2:学生和咨询师在线一对一交流
使用面向对象封装:发送端
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
public class TalkSend implements Runnable {
private DatagramSocket client;
private BufferedReader reader;
private String toIP;
private int toPort;
public TalkSend(int port,String toIP,int toPort){
this.toIP=toIP;
this.toPort=toPort;
try {
client=new DatagramSocket(port);
reader=new BufferedReader(new InputStreamReader(System.in));
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
String data;
try {
data = reader.readLine();
byte[] datas = data.getBytes();
//3.封装成DatagramPacket 包裹,需要指定目的地
DatagramPacket packet = new DatagramPacket(datas, 0, datas.length,
new InetSocketAddress(toIP, toPort));
//4.发送包裹send(DatagramPacket p)
client.send(packet);
if (data.equals("bye")) {
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
//5.释放资源
client.close();
}
}
使用面向对象封装:接收端
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class TalkReceive implements Runnable {
private DatagramSocket server;
private String from;
public TalkReceive(int port,String from){
this.from=from;
try {
server=new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while(true) {
//2.准备容器 封装成DatagramPacket 包裹
byte[] container = new byte[1024 * 60];
DatagramPacket packet = new DatagramPacket(container, 0, container.length);
//3.阻塞式接收包裹receive(DatagramPacket p)
try {
server.receive(packet);
} catch (IOException e) {
e.printStackTrace();
}
//4.分析数据
// byte[] getData()
// getLength()
byte[] datas = packet.getData();
int len = packet.getLength();
String data=new String(datas,0,len);
System.out.println(from+":"+data);
if(data.equals("bye")){
break;
}
}
//5.释放资源
server.close();
}
}
对象:学生
public class TalkStudent {
public static void main(String[] args){
new Thread(new TalkSend(6666,"localhost",9999)).start();//发送
new Thread(new TalkReceive(8888,"老师")).start();//接收
}
}
对象:老师
public class TalkTeacher {
public static void main(String[] args){
new Thread(new TalkReceive(9999,"学生")).start();//接收
new Thread(new TalkSend(7777,"localhost",8888)).start();//发送
}
}