文章目录
- 一、网络相关的概念
- 二、InetAddresss类
- 三、Socket
- 3.1 基本介绍
- 四、TCP网络通信编程
- 4.1 应用案例1(使用字节流)
- 4.2 应用案例2(使用字节流)
- 4.3 应用案例3(使用字符流)
- 4.4 应用案例4(TCPFileCopy)
- 4.5 netstat 指令
- 4.6 TCP网络通讯不为人知的秘密
- 五、UDP网络通信编程(了解)
一、网络相关的概念
二、InetAddresss类
package com.gyh.api;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* @author Gao YongHao
* @version 1.0
*/
public class API_ {
public static void main(String[] args) throws UnknownHostException {
// 1. 获取本机的 InetAddress 对象
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(localHost); // DESKTOP-P3G09I0/192.168.246.1
// 2. 根据指定主机名/域名获取ip地址对象 getByName
InetAddress host1 = InetAddress.getByName("DESKTOP-P3G09I0");
System.out.println(host1); // DESKTOP-P3G09I0/192.168.246.1
// 3. 根据域名获取 InetAddress 对象
InetAddress host2 = InetAddress.getByName("www.baidu.com");
System.out.println(host2); // www.baidu.com/14.215.177.39
// 4. 通过 InetAddress 对象,获取对应的地址
String hostAddress = host2.getHostAddress();
System.out.println("host2 对应的ip地址为:" + hostAddress); // host2 对应的ip地址为:14.215.177.39
// 5. 通过 InetAddress 对象,获取对应的主机名/或者域名
String hostName = host2.getHostName();
System.out.println(hostName);// www.baidu.com
}
}
三、Socket
3.1 基本介绍
所谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议栈进行交互的接口
摘自:百度百科
四、TCP网络通信编程
4.1 应用案例1(使用字节流)
// 服务器端
package com.gyh.api;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author Gao YongHao
* @version 1.0
*/
public class SocketTCP01Server {
public static void main(String[] args) throws IOException {
// 1.在本机 的9999 端口监听,等待连接
// 细节:要求在本机没有其他服务在监听9999
// ServerSocket 可以通过 accept() 返回多个Socket[多个客户端连接服务器的并发]
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务端,在9999端口监听,等待连接..");
// 2. 当没有客户端连接9999端口时,程序会阻塞,等待连接
// 如果有客户端连接,则会返回 Socket 对象,程序继续
Socket socket = serverSocket.accept();
System.out.println("服务器端 socket= " + socket.getClass());
// 3. 通过 socket.getInputStream() 读取客户端写入到数据通道的数据,显示
InputStream inputStream = socket.getInputStream();
byte[] buf = new byte[1024];
int readLen = 0;
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
while ((readLen = bufferedInputStream.read(buf)) != -1) {
System.out.println(new String(buf, 0, readLen)); // 根据读取到的实际长度,显示内容
}
// 5. 关闭流对象和socket,serverSocket,必须关闭
bufferedInputStream.close();
socket.close();
serverSocket.close();
}
}
// 客户端
package com.gyh.api;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
/**
* @author Gao YongHao
* @version 1.0
*/
public class SocketTCP01Client {
public static void main(String[] args) throws IOException {
// 思路:
// 1. 连接服务器(ip,端口号)
// 解读:连接服务器的 9999 端口
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
System.out.println("客户端 socket返回=" + socket.getClass());
// 2. 连上后,生成Socket,通过socket.getOutputStream()
// 得到和socket关联的输出流对象
OutputStream outputStream = socket.getOutputStream();
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
// 3. 通过输出流,写入数据到 数据通道
bufferedOutputStream.write("你好".getBytes());
// 4. 关闭流对象和socket,必须关闭
bufferedOutputStream.close();
socket.close();
System.out.println("客户端退出");
}
}
4.2 应用案例2(使用字节流)
// 服务器端
package com.gyh.api;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author Gao YongHao
* @version 1.0
*/
public class SocketTCP02Server {
public static void main(String[] args) throws IOException {
// 1.在本机 的9999 端口监听,等待连接
// 细节:要求在本机没有其他服务在监听9999
// ServerSocket 可以通过 accept() 返回多个Socket[多个客户端连接服务器的并发]
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务端,在9999端口监听,等待连接..");
// 2. 当没有客户端连接9999端口时,程序会阻塞,等待连接
// 如果有客户端连接,则会返回 Socket 对象,程序继续
Socket socket = serverSocket.accept();
System.out.println("服务器端 socket= " + socket.getClass());
// 3. 通过 socket.getInputStream() 读取客户端写入到数据通道的数据,显示
InputStream inputStream = socket.getInputStream();
byte[] buf = new byte[1024];
int readLen = 0;
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
while ((readLen = bufferedInputStream.read(buf)) != -1) {
System.out.println(new String(buf, 0, readLen)); // 根据读取到的实际长度,显示内容
}
// 4. 回复
OutputStream outputStream = socket.getOutputStream();
outputStream.write("Hello,client".getBytes());
// 设置结束标记
socket.shutdownOutput();
// 5. 关闭流对象和socket,serverSocket,必须关闭
outputStream.close();
bufferedInputStream.close();
socket.close();
serverSocket.close();
System.out.println("服务器端退出");
}
}
// 客户端
package com.gyh.api;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
/**
* @author Gao YongHao
* @version 1.0
*/
public class SocketTCP02Client {
public static void main(String[] args) throws IOException {
// 思路:
// 1. 连接服务器(ip,端口号)
// 解读:连接服务器的 9999 端口
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
System.out.println("客户端 socket返回=" + socket.getClass());
// 2. 连上后,生成Socket,通过socket.getOutputStream()
// 得到和socket关联的输出流对象
OutputStream outputStream = socket.getOutputStream();
// 3. 通过输出流,写入数据到 数据通道
outputStream.write("Hello,server".getBytes());
// 设置一个结束标记
socket.shutdownOutput();
// 4. 接收信息
byte[] buf = new byte[1024];
int readLen = 0;
InputStream inputStream = socket.getInputStream();
while ((readLen = inputStream.read(buf)) != -1) {
System.out.println(new String(buf, 0, readLen));
}
// 5. 关闭流对象和socket,必须关闭
// 发送信息
outputStream.close();
inputStream.close();
socket.close();
System.out.println("客户端退出");
}
}
4.3 应用案例3(使用字符流)
// 服务器端
package com.gyh.api;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
/**
* @author Gao YongHao
* @version 1.0
*/
public class SocketTCP03Server {
public static void main(String[] args) throws IOException {
// 1.在本机 的9999 端口监听,等待连接
// 细节:要求在本机没有其他服务在监听9999
// ServerSocket 可以通过 accept() 返回多个Socket[多个客户端连接服务器的并发]
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务端,在9999端口监听,等待连接..");
// 2. 当没有客户端连接9999端口时,程序会阻塞,等待连接
// 如果有客户端连接,则会返回 Socket 对象,程序继续
Socket socket = serverSocket.accept();
System.out.println("服务器端 socket= " + socket.getClass());
// 3. IO读取,使用字符流,使用 InputStreamReader 将 inputStream 转成字符流
String content;
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while ((content = bufferedReader.readLine()) != null) {
System.out.println(content);
}
// 4. IO读取,使用字符流,使用 OutputStreamWriter 将 outStream 转成字符流
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bufferedWriter.write("Hello,client");
bufferedWriter.newLine();// 插入一个换行符,表示写入的内容结束 注意:要求对方使用readLine()的方式来读
bufferedWriter.flush(); // 如果使用字符流,需要手动刷新,否则数据不会写入数据通道
socket.shutdownOutput();
// 5. 关闭流对象和socket,serverSocket,必须关闭
bufferedWriter.close();
bufferedReader.close();
socket.close();
serverSocket.close();
System.out.println("服务器端退出");
}
}
// 客户端
package com.gyh.api;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
/**
* @author Gao YongHao
* @version 1.0
*/
public class SocketTCP03Client {
public static void main(String[] args) throws IOException {
// 思路:
// 1. 连接服务器(ip,端口号)
// 解读:连接服务器的 9999 端口
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
System.out.println("客户端 socket返回=" + socket.getClass());
// 2. 连上后,生成Socket,通过socket.getOutputStream()
// 使用字符流,使用 OutputStreamWriter 将 outStream 转成字符流
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
// 3. 通过输出流,写入数据到 数据通道
bufferedWriter.write("Hello,server");
bufferedWriter.newLine();// 插入一个换行符,表示写入的内容结束 注意:要求对方使用readLine()的方式来读
bufferedWriter.flush(); // 如果使用字符流,需要手动刷新,否则数据不会写入数据通道
socket.shutdownOutput(); // 要添加,否则对方不知道说完没有
// 4. 接收信息
String content;
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while ((content = bufferedReader.readLine()) != null) {
System.out.println(content);
}
// 5. 关闭流对象和socket,必须关闭
// 发送信息
bufferedReader.close();
bufferedWriter.close();
socket.close();
System.out.println("客户端退出");
}
}
4.4 应用案例4(TCPFileCopy)
// 服务器端
package com.gyh.api;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author Gao YongHao
* @version 1.0
*/
public class SocketTCP04Server {
public static void main(String[] args) throws IOException {
// 启动一个端口号为9999的服务
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务端等待连接....");
// 接收一个socket信息,服务器未连接会在此阻塞
Socket socket = serverSocket.accept();
byte[] buf = new byte[1024];
int readLen = 0;
BufferedInputStream bufferedInputStream = new BufferedInputStream(socket.getInputStream());
// 保存至本地 src下的qie.png
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("src\\ie.png"));
while ((readLen = bufferedInputStream.read(buf)) != -1) {
bufferedOutputStream.write(buf, 0, readLen);
}
bufferedOutputStream.close(); // 关闭文件输出流
// 接收完毕回复
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bufferedWriter.write("收到图片");
bufferedWriter.flush();
socket.shutdownOutput();
// 关闭资源
bufferedWriter.close();
bufferedInputStream.close();
socket.close();
serverSocket.close();
System.out.println("服务端关闭");
}
}
// 客户端
package com.gyh.api;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* @author Gao YongHao
* @version 1.0
*/
public class SocketTCP04Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
// 发送图片
byte[] buf = new byte[1024];
int readLen;
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("C:\\Users\\Gaoyonghao\\Desktop\\1.PNG"));
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(socket.getOutputStream());
while ((readLen = bufferedInputStream.read(buf)) != -1) {
bufferedOutputStream.write(buf, 0, readLen);
}
// 发送完毕
bufferedInputStream.close(); // 文件输入流关闭
bufferedOutputStream.flush();
socket.shutdownOutput(); // 设置写入数据的结束标记
// 接收服务器端的消息
String content;
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while ((content = bufferedReader.readLine()) != null) {
System.out.println(content);
}
//关闭资源
bufferedReader.close();
bufferedOutputStream.close();
socket.close();
System.out.println("客户端关闭");
}
}
4.5 netstat 指令
4.6 TCP网络通讯不为人知的秘密
五、UDP网络通信编程(了解)
// 接收方
package com.gyh.api;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
* @author Gao YongHao
* @version 1.0
*/
public class SocketUDP01Receiver {
public static void main(String[] args) throws IOException {
// 1. 创建一个 DatagramSocket 对象,准备在 9999 端口接收数据
DatagramSocket datagramSocket = new DatagramSocket(9999);
// 2. 构建一个 DatagramPacket ,准备接收数据
// 在前面讲解 UDP 协议时,说过一个数据包最大为 64k
byte[] bytes = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length);
// 调用 接收方法
// 提示:当有数据包发送到 本机的9999端口时,就会接收到数据
// 如果没有数据包发送到 本机的9999端口,就会阻塞等待
System.out.println("接收端A 等待接收数据");
datagramSocket.receive(datagramPacket);
// 4. 可以把packet 进行拆包,取出数据,并显示
int length = datagramPacket.getLength(); // 实际接收到的数据字节长度
byte[] data = datagramPacket.getData();
String content = new String(data, 0, length);
System.out.println(content);
byte[] message = "好的,明天见".getBytes();
datagramSocket.send(new DatagramPacket(message, message.length, InetAddress.getByName("127.0.0.1"), 8888));
// 关闭资源
datagramSocket.close();
System.out.println("A端退出");
}
}
// 发送方
package com.gyh.api;
import java.io.IOException;
import java.net.*;
/**
* @author Gao YongHao
* @version 1.0
*/
public class SocketUDP01Sender {
public static void main(String[] args) throws IOException {
// 1. 创建 DatagramSocket 对象,准备在 8888 端口发送、接收数据
DatagramSocket datagramSocket = new DatagramSocket(8888);
// 2. 将需要发送的数据,封装到 DatagramPacket 对象
byte[] content = "Hello,明天吃火锅".getBytes();
// 说明:封装的 DatagramPacket对象 content内容字节数组,content.length,主机(IP),端口
DatagramPacket datagramPacket = new DatagramPacket(content, content.length, InetAddress.getLocalHost(), 9999);
datagramSocket.send(datagramPacket);
// 3. 接收从receiver端回复的信息
byte[] bytes = new byte[1024];
DatagramPacket datagramPacket1 = new DatagramPacket(bytes, bytes.length);
datagramSocket.receive(datagramPacket1);
int readLen = datagramPacket1.getLength();
byte[] data = datagramPacket1.getData();
System.out.println(new String(data, 0, readLen));
datagramSocket.close();
System.out.println("B端退出");
}
}