网络编程
只要有你在,我便我所不能
一、简介
二、IP和端口号
1. IP
IP用JAVA中的InetAddress类来表示
- 1)如何实例化:
InetAddress inet = InetAddress.getByName("www.baidu.com");
- 获取本机IP:
InetAddress inet2 = InetAddress.getLocalHost();
- 获取本机IP:
- 2)常用方法:
- 获取IP:getHostAddress()
- 获取域名:getHostName()
2. 端口号
① 简介
- 不同进程有不同端口号
- 16位整数:0-65535
- JAVA中使用InetSocketAddress类来表示:
InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 8080);
② 分类
- 公认端口:0~1023
- 注册端口:1024~49151
- 动态/私有端口:49152~65535
③ 套接字
- 端口号与IP地址组合得出一个网络套接字:Socket
④ cmd命令
- 查看所有端口:netstat -ano
- 查看指定端口:netstat -aon|findstr “port”
- 查看具体的进程:tasklist|findstr “port”
⑤ 常用方法
- 获取IP:getAddress()
- 获取域名:getHostAddress()
- 获取端口:getPort()
3. URL
- 1)URL(同一资源定位器)组成:https://www.google.com:80/index.html
- 协议
- 存放资源的主机域名
- 端口号
- 资源文件名
- 2)定义
URL url = new URL("https://www.baidu.com:80/index.html?username=zm&age=18#a");
- 3)常用方法
- 协议:getProtocol()
- 域名|ip:getHost()
- 端口:getPort()
- 请求资源1:getFile():/index.html?username=zm&age=18
- 请求资源2:getPath():/index.html
- 参数:getQuery()
- 锚点:getRef()
三、网络协议
传输层的两个协议TCP、UDP协议
1. TCP
- 先建立连接
- 传输前,采用“三次握手”方式,点对点通信,可靠
- TCP通信的两个进程:客户端、服务端
- 可进行大数据量的传输
- 传输完毕,需要释放连接,效率低
2. UDP
- 将数据、源、目的封装成数据包,不需要建立连接
- 每个数据报大小限制在64K
- 不可靠
- 可以广播发送
- 发送数据时无需释放资源, 开销小,速度快
四、TCP网络编程
1. 步骤
① 服务端
- 1)指定端口,使用ServerSocket创建服务器
- 2)阻塞式等待连接,accept()
- 3)操作输入输出流读取数据
- 4)关闭资源
② 客户端
- 1)建立连接:创建Socket客户端 + 服务端地址和端口
- 2)操作输入输出流
- 3)释放资源
2. 实现
/**
* 实现TCP网络编程
*
* 案例1.客户端发送信息给服务端,服务端将数据显示在控制台
*/
public class Test01TCP {
//客户端
@Test
public void client() {
//1.创建Socket对象,指明服务器端的ip和端口号
Socket socket = null;
OutputStream os = null;
try {
InetAddress inet = InetAddress.getByName("localhost");
socket = new Socket(inet, 8899);
//2.获取输出流,用于输出数据
os = socket.getOutputStream();
//3.写出数据
os.write("你好,我是客户端mm".getBytes());
} catch (IOException e) {
e.printStackTrace();
}finally {
//4.资源关闭
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//服务端
@Test
public void server(){
ServerSocket ss = null;
Socket socket = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
try {
//1.创建服务器端的ServerSocket,指明自己的端口号
ss = new ServerSocket(8899);
//2.调用accept()方法,接受客户端的socket
socket = ss.accept();
//3.获取输入流
is = socket.getInputStream();
//这样写中文数据可能会有乱码
// byte[] buffer = new byte[20];
// int len;
// while ((len = is.read(buffer)) != -1) {
// String temp = new String(buffer, 0, len);
// System.out.println(temp);
// }
//
//4.读取数据
baos = new ByteArrayOutputStream();
byte[] buffer = new byte[20];
int len;
while ((len = is.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
System.out.println(baos.toString());
System.out.println("收到了来自于:" + socket.getInetAddress().getHostAddress() + "的数据");
} catch (IOException e) {
e.printStackTrace();
} finally {
//5.关闭资源
if (baos != null) {
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (ss != null) {
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
3. 案例
更多案例去看project/java/java se/idea/javaSE01 中的代码
五、UDP网络编程
1. 简介
- DatagramSocket:用于发送或接收数据包的套接字
- DatagramPacket:数据包
2. 实现
① 客户端
@Test
public void client() throws Exception {
/*
* 1.使用DatagramSocket 指定端口,创建接收端
* 2.准备数据,转成字节数组
* 3.封装成DatagramPacket包裹,指明目的地
* 4.发送包裹send(DatagramPacket)
* 5.释放资源
* */
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)
client.send(packet);
//5.释放资源
client.close();
}
② 服务端
@Test
public void sever() throws Exception {
/*
* 1.使用DatagramSocket 指定端口,创建接收端
* 2.准备容器,封装成DatagramPacket包裹
* 3.阻塞式接收receive(DatagramPacket)
* 4.分析数据
* getData()
* getLength()
* 5.释放资源
* */
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)
server.receive(packet);
//4.分析数据
byte[] datas = packet.getData();
int len = packet.getLength();
System.out.println(new String(datas, 0, len));
//5.释放资源
server.close();
}
3. 简易对话
添加了多线程、和面向对象封装
① 封装发送端
/**
* UDP编程
*
* 面向对象封装:发送端
*/
public class Test03_Send implements Runnable{
private DatagramSocket client;
private BufferedReader reader;
private String toIP;
private int toPort;
//构造器,初始化IP、端口信息
public Test03_Send(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() {
System.out.println(Thread.currentThread().getName() + "启动...");
while (true) {
String data = null;
try {
data = reader.readLine();
byte[] datas = data.getBytes();
//3.打包数据
DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress(this.toIP, this.toPort));
//4.发送包
client.send(packet);
if ("bye".equals(data)){
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
//5.释放资源
client.close();
}
}
② 封装接收端
/**
* UDP编程
*
* 面向对象封装:接收端
*/
public class Test03_Receive implements Runnable {
private DatagramSocket server;
private String from;
//构造器,初始化端口
public Test03_Receive(int port, String from) {
this.from = from;
try {
server = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "启动...");
while (true) {
//2.准备容器,接收数据,准备包裹,包裹数据
byte[] container = new byte[1024*60];
DatagramPacket packet = new DatagramPacket(container, 0, container.length);
try {
//3.阻塞式接收数据
server.receive(packet);
//4.处理数据
byte[] datas = packet.getData();
int len = packet.getLength();
String data = new String(datas, 0, len);
System.out.println(from + ":" + data);
if ("bye".equals(data)){
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
//5.关闭资源
server.close();
}
}
③ 学生
/**
* 加入多线程:实现双向交流
* 学生端
* 接收端口:7777
* 发送端口:8888
*/
public class Test03_Student {
public static void main(String[] args) {
//发送
Thread student_send = new Thread(new Test03_Send(8888, "localhost", 9999));
student_send.start();
//接收
Thread student_receive = new Thread(new Test03_Receive(7777, "老师"));
student_receive.start();
}
}
④ 老师
/**
* 加入多线程:实现双向交流
* 老师端
* 接收端口:9999
* 发送端口:6666
*/
public class Test03_Teacher {
public static void main(String[] args) {
//接收
Thread teacher_receive = new Thread(new Test03_Receive(9999, "学生"));
teacher_receive.start();
//发送
Thread teacher_send = new Thread(new Test03_Send(6666, "localhost", 7777));
teacher_send.start();
}
}
更多案例去看project/java/java se/idea/javaSE01 中的代码