一、什么是网络编程
- 可以让设备中的程序与网络上其他设备的程序进行数据交互
二、基本的通信架构
1.C/S架构(Client客户端/Server服务端)
- 客户端需要程序员开发,用户需要安装
- 服务端需要开发实现
2.B/S架构(Browser浏览器/Server服务端)
- 客户端不需要程序员开发,用户需要安装浏览器
- 服务端需要开发
三、网络通信关键三要素
1.IP地址:设备在网络的地址
- IP(Internet Protocol):全称“互联网协议地址”,是分配给上网设备的唯一标识
- IP地址有两种形式:IPv4、IPv6
- 公网IP、内网IP
- 特殊IP地址
- 127.0.0.1、localhost:代表本机IP,只会寻找当前所在的主机
- 常用IP命令
- ipconfig:查看本机IP地址
- ping IP地址:检查网络是否连通
- InetAddress类代表IP对象
public static void main(String args[]) throws IOException {
//1.获取本机IP地址对象
InetAddress ip1 = InetAddress.getLocalHost();
System.out.println(ip1.getHostName());
System.out.println(ip1.getHostAddress());
//2.获取指定IP或者域名的IP地址对象
InetAddress ip2 = InetAddress.getByName("www.baidu.com");
System.out.println(ip2.getHostName());
System.out.println(ip2.getHostAddress());
//检查是否连通
System.out.println(ip2.isReachable(6000));
}
2.端口:应用程序在设备中唯一的标识
- 标记正在计算机设备上运行的应用程序,被规定一个16位的二进制
分类
- 周知端口
- 注册端口
- 动态端口
3.协议:连接和数据在网络中传输的规则
开放式网络互联标准:OSI网络参考模型
- TCP/IP网络模型:事实上的国际标准
- 应用层
- 传输层
- 网络层
- 数据链路+物理层
传输层的2个通信协议
- UDP(User Datagram Protocol):用户数据报协议
- TCP(Transmission Control Protocol):传输控制协议
UDP协议
- 特点:无连接,不可靠通信
- 不事先建立连接,数据按照包发
TCP协议
- 特点:面向连接、可靠通信
- TCP的最终目的:要保证在不可靠的信道上实现可靠的传输
- 三个步骤实现可靠传输
- 三次握手建立可靠连接:确定通信双方,收发信息都是正常无问题
- 传输数据进行确定
- 四次握手断开连接:确保双方数据的收发都已经完成
四、Java实现网络通信
1.java提供了一个java.net.DatagramSocket类来实现UDP通信
-
客户端
public static void main(String args[]) throws Exception {
//1.创建客户端对象(端菜出去的人)
DatagramSocket socket = new DatagramSocket(port:6666);
//2.创建数据包对象封装要发出去的数据(创建一个装菜的盘子)
/*
* public DatagramPacket(byte buf[], int length,
* InetAddress address, int port)
* 参数一:封装要发出去的数据
* 参数二:发送出去的数据大小(字节个数)
* 参数三:服务端的IP地址
* 参数四:服务端程序的端口
*/
byte bytes[] = "我是快乐的客户端".getBytes();
DatagramPacket packet = new DatagramPacket(bytes, bytes.length,
InetAddress.getLocalHost(),6666);
//3.开始正式发送这个数据包的数据出去
socket.send(packet);
System.out.println("客户端发送完毕-----");
socket.close();//释放资源
}
-
服务端
public static void main(String[] args) throws IOException {
System.out.println("-------服务端启动-------");
//1.创建一个服务端对象注册端口
DatagramSocket socket = new DatagramSocket(6666);
//2.创建一个数据包对象,用于接收数据的
byte[] buffer = new byte[1024 * 64];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
//3.开始正式使用数据包来接收客户端发来的数据
socket.receive(packet);
//4.从字节数组中,把接收到的数据直接打印出来
int len = packet.getLength();
String rs = new String(buffer, 0, len);
System.out.println(rs);
System.out.println(packet.getAddress().getHostAddress());
System.out.println(packet.getPort());
}
使用UDP通信实现:多发多收信息
//客户端多次发送信息
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请说:");
String msg = sc.nextLine();
//一旦发现用户输入exit的命令,就退出客户端
if ("exit".equals(msg)){
System.out.println("下次再来,退出成功");
socket.close();
break;
}
byte[] bytes = msg.getBytes();
DatagramPacket packet = new DatagramPacket(bytes, bytes.length,
InetAddress.getLocalHost(),6666);
//3.开始正式发送这个数据包的数据出去
socket.send(packet);
}
//服务端接收
while (true) {
socket.receive(packet);
//4.从字节数组中,把接收到的数据直接打印出来
int len = packet.getLength();
String rs = new String(buffer, 0, len);
System.out.println(rs);
System.out.println(packet.getAddress().getHostAddress());
System.out.println(packet.getPort());
}
2.java提供了一个java.net.Socket类来实现TCP通信
- 客户端
//1.创建socket对象,并同时请求与服务端程序的连接
Socket socket = new Socket("127.0.0.1",8888);
//2.从socket通信管道得到一个字节输出流,用来发数据给服务端程序
OutputStream os = socket.getOutputStream();
//3.把低级的字节输出流包装成数据输出流
DataOutputStream dos = new DataOutputStream(os);
//4.开始写数据出去
dos.writeUTF("我喜欢你");
dos.close();
- 服务端
public static void main(String[] args) throws IOException {
System.out.println("-----服务端启动成功-----");
//1.创建ServerSocket对象,同时为服务端注册端口
ServerSocket serverSocket = new ServerSocket(8888);
//2.调用accept方法,等待客户端的连接请求
Socket socket = serverSocket.accept();
//3.从socket通信管道得到一个字节输入流
InputStream is = socket.getInputStream();
//4.把原始的字节输入流包装成数据输入流
DataInputStream dis = new DataInputStream(is);
//5.使用数据输入流读取客户端发送过来的信息
String rs = dis.readUTF();
System.out.println(rs);
//获取客户端的IP地址
System.out.println(socket.getRemoteSocketAddress());
dis.close();
socket.close();
}
使用TCP通信实现:多发多收信息
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请说:");
String msg = sc.nextLine();
if ("exit".equals(msg)){
System.out.println("下次再来,退出成功");
dos.close();
socket.close();
break;
}
//4.开始写数据出去
dos.writeUTF(msg);
dos.flush();
}
while (true) {
try {
String rs = dis.readUTF();
System.out.println(rs);
} catch (IOException e) {
//服务端追踪客户端的离线
System.out.println(socket.getRemoteSocketAddress() + "离线了");
socket.close();
dis.close();
break;
}