21章网络通信

发布时间:2023年12月17日

21.1——网络程序设计基础

网络程序设计编写得到是与其他计算机进行通信的程序

在Java中,网络通信是通过使用各种类和接口来实现的,常见的包括Socket、ServerSocket、DatagramSocket等。Java提供了丰富的网络编程工具,可以进行TCP和UDP通信,并且还提供了NIO(New I/O)包,用于更高效地处理非阻塞I/O操作。以下是Java网络通信的主要特点和使用方法的总结:

IP协议

IP 是Internet Protocol的简称,是一种网络协议。Interet 网络采用的协议是 TCP/P 协议,其全称是Transmission Control Protocol/Internet Protocol。Internet 依靠 TCP/P 协议,在全球范围内实现了不硬件结构、不同操作系统、不同网络系统间的互联。在 Intenet 网络上存在着数以亿计的主机,每台3机都用网络为其分配的 Intermet 地址代表自己,这个地址就是 IP 地址。到目前为止,IP 地址用 4个节,也就是 32 位的二进制数来表示,称为 IPv4。为了便于使用,通常取用每个字节的十进制数,并每个字节之间用圆点隔开来表示 P 地址,如 192.168.1.1。现在人们正在试验使用 16 个字节来表示地址,这就是 IPv6,但IPv6 还没有投入使用。

1. **TCP通信**:
? ?- 使用Socket和ServerSocket类可以实现TCP通信,Socket用于客户端,ServerSocket用于服务器端。客户端可以通过Socket与服务器端建立连接,并实现数据的传输和通信。

2. **UDP通信**:
? ?- 使用DatagramSocket和DatagramPacket类可以实现UDP通信,UDP通信是无连接的,使用简单,适合对数据传输速度要求较高的场景。

3. **网络地址和URL处理**:
? ?- 使用InetAddress类表示IP地址,URL类用于处理URL链接,URLConnection类用于代表应用程序和URL之间的通信链接。

4. **NIO编程**:
? ?- Java提供了NIO(New I/O)包,通过Channel、Buffer和Selector等组件,能够更好地处理多路复用的网络通信。

5. **并发处理**:
? ?- 多线程在网络编程中很常见,能够提高并发处理能力,Java提供了丰富的并发处理支持,例如通过Executor框架管理线程池,实现高效的并发网络通信。

总的来说,Java提供了丰富和灵活的网络编程工具和API,能够满足各种网络通信需求,开发人员可以根据实际情况选择合适的网络通信方式,并利用Java提供的工具和API,实现客户端和服务器端的连接、数据传输等功能。

当开发Java网络通信应用时,一些关键的注意事项如下:

1. **异常处理**:在网络通信过程中,可能会出现各种异常,如连接超时、IO异常等。因此,需要在代码中进行良好的异常处理,以保证程序的稳定性和可靠性。

2. **线程管理**:网络通信通常需要面对多个客户端的并发请求,因此需要合理地管理线程以处理这些请求。Java提供了丰富的线程管理和同步工具,开发人员需要谨慎设计和管理线程以确保程序的高效性和安全性。

3. **安全性**:网络通信涉及到数据传输,因此数据的安全性是至关重要的。在开发网络通信应用时,需要考虑数据加密、身份验证等安全机制,以保护数据不受未经授权的访问和篡改。

4. **性能优化**:为了提高网络通信应用的性能,可以采用一些性能优化手段,比如使用NIO实现非阻塞IO、合理设计协议和数据包格式,以及使用缓存等技术来提升程序的响应速度和吞吐量。

5. **协议和数据格式**:网络通信通常需要事先定义协议和数据格式,以确保不同系统之间能够正确地进行数据交换。因此,在开发网络通信应用时,需要深入理解所使用的协议和数据格式,并进行合理的设计和解析。

6. **测试与调试**:对于网络通信应用,充分的测试和调试是非常重要的。需要进行单元测试、集成测试以及模拟网络环境的压力测试,以确保应用程序的稳定性和健壮性。

总的来说,Java网络通信开发需要综合考虑多方面的因素,包括异常处理、线程管理、安全性、性能优化、协议和数据格式设计,以及测试与调试等,通过合理的设计和实践,可以开发出稳定、高效、安全的网络通信应用。

当涉及到Java网络通信的开发实践时,以下是一些建议:

1. **充分理解网络基础知识**:在进行Java网络通信开发之前,建议对网络基础知识进行充分理解,包括TCP/IP协议、HTTP协议、Socket通信等,这有助于更好地理解Java网络通信的工作原理和机制。

2. **选择合适的网络库和框架**:Java生态系统中有许多优秀的网络开发库和框架,比如Netty、OkHttp、Apache HttpClient等,开发人员可以根据项目需求选择合适的库和框架来简化网络通信开发。

3. **遵循良好的设计模式**:在进行网络通信应用的开发时,遵循良好的设计模式可以提高代码的可读性、可维护性和可扩展性,比如使用工厂模式、单例模式、观察者模式等。

4. **灵活应对网络异常**:网络通信中各种异常是常见的,比如超时、连接中断、数据包丢失等,开发人员需要编写健壮的代码来处理这些异常情况,保证应用的稳定性。

5. **进行代码复用**:在网络通信应用的开发中,可以将相关的网络通信代码进行封装和复用,以便在不同模块或不同应用中进行共享使用,提高开发效率。

6. **考虑跨平台性**:如果应用需要在不同操作系统下运行,需要考虑网络通信代码的跨平台性,确保在不同环境下也能正常工作。

7. **持续学习和实践**:由于网络通信技术日新月异,建议开发人员持续学习最新的网络通信技术和实践经验,不断提升自己的网络通信开发能力。

虽然网络通信在Java开发中具有挑战性,但通过不断学习和实践,可以逐渐掌握网络通信开发的技能,从而开发出高效、稳定的网络通信应用。

21.2.1——InetAddress类

示例1:

import java.net.InetAddress;
import java.net.UnknownHostException;
?
public class Address {
?? ?public static void main(String[] args) {
?? ??? ?InetAddress ip;?? ?//创建InetAddress对象
?? ??? ?try{
?? ??? ??? ?ip= InetAddress.getLocalHost();
?? ??? ??? ?String localname = ip.getHostName();
?? ??? ??? ?String localip = ip.getHostAddress();
?? ??? ??? ?System.out.println("本机名:"+localname);
?? ??? ??? ?System.out.println("本机IP地址:"+localip);
?? ??? ?}catch(UnknownHostException e) {
?? ??? ??? ?e.printStackTrace();
?? ??? ?}
?? ?}
}

21.2.2——ServerSocket类
java,net 包中的 ServerSocket 类用于表示服务器套接字,其主要功能是等待来自网络上的“请求”它可通过指定的端口来等待连接的套接字。服务器套接字一次可以与一个套接字连接。如果多台客户机同时提出连接请求,服务器套接字会将请求连接的客户机存入列队中,然后从中取出一个套接字.与服务器新建的套接字连接起来。若请求连接数大于最大容纳数,则多出的连接请求被拒绝。队列的默认大小是 50。

21.2.3——TCP网络程序设计
明白了TCP 程序工作的过程,就可以编写 TCP 服务器程序了。在网络编程中,如果只要求客户机疆务器发送消息,不要求服务器向客户机发送消息,称为单向通信。客户机套接字和服务器套接字接成功后,客户机通过输出流发送数据,服务器则通过输入流接收数据。下面是简单的单向通信的

例题2
import java.io.*;
import java.net.*;
?
public class MyServer {
?? ?private ServerSocket server; // 服务器套接字
?? ?private Socket socket; // 客户端套接字
?
?? ?void start() {// 启动服务器
?? ??? ?try {
?? ??? ??? ?server = new ServerSocket(8998); // 服务器启用8998端口
?? ??? ??? ?System.out.println("服务器套接字已经创建成功");
?? ??? ??? ?while (true) {
?? ??? ??? ??? ?System.out.println("等待客户端的连接");
?? ??? ??? ??? ?socket = server.accept(); // 服务器监听客户端连接
?? ??? ??? ??? ?// 根据套接字字节流创建字符输入流
?? ??? ??? ??? ?BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
?? ??? ??? ??? ?while (true) {// 循环接受信息
?? ??? ??? ??? ??? ?String message = reader.readLine();// 读取一行文本
?? ??? ??? ??? ??? ?if ("exit".equals(message)) {// 如果客户端发来的内容为“exit”
?? ??? ??? ??? ??? ??? ?System.out.println("客户端退出");
?? ??? ??? ??? ??? ??? ?break;// 停止接受信息
?? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ?System.out.println("客户端:" + message);
?? ??? ??? ??? ?}
?? ??? ??? ??? ?reader.close(); // 关闭流
?? ??? ??? ??? ?socket.close(); // 关闭套接字
?? ??? ??? ?}
?? ??? ?} catch (IOException e) {
?? ??? ??? ?e.printStackTrace();
?? ??? ?}
?? ?}
?
?? ?public static void main(String[] args) {
?? ??? ?MyServer tcp = new MyServer();
?? ??? ?tcp.start(); // 启动服务器
?? ?}
}

2:

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.Socket;
import javax.swing.*;
?
public class MyClient extends JFrame {
?? ?private PrintWriter writer;// 根据套接字字节流创建的字符输出流
?? ?Socket socket; // 客户端套接字
?? ?private JTextArea area = new JTextArea();// 展示信息的文本域
?? ?private JTextField text = new JTextField(); // 发送信息的文本框
?
?? ?public MyClient() {
?? ??? ?setTitle("向服务器送数据");
?? ??? ?setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
?? ??? ?Container c = getContentPane(); // 主容器
?? ??? ?JScrollPane scrollPane = new JScrollPane(area);// 滚动面板
?? ??? ?getContentPane().add(scrollPane, BorderLayout.CENTER);
?? ??? ?c.add(text, "South"); // 将文本框放在窗体的下部
?? ??? ?text.addActionListener(new ActionListener() {// 文本框触发回车事件
?? ??? ??? ?public void actionPerformed(ActionEvent e) {
?? ??? ??? ??? ?writer.println(text.getText().trim()); // 将文本框中的信息写入流
?? ??? ??? ??? ?area.append(text.getText() + '\n'); // 将文本框中的信息显示在文本域中
?? ??? ??? ??? ?text.setText(""); // 将文本框清空
?? ??? ??? ?}
?? ??? ?});
?? ?}
?
?? ?private void connect() { // 连接服务器方法
?? ??? ?area.append("尝试连接\n"); // 文本域中提示信息
?? ??? ?try {
?? ??? ??? ?socket = new Socket("127.0.0.1", 8998); // 连接本地计算机的8998端口
?? ??? ??? ?writer = new PrintWriter(socket.getOutputStream(), true);
?? ??? ??? ?area.append("完成连接\n");
?? ??? ?} catch (IOException e) {
?? ??? ??? ?e.printStackTrace();
?? ??? ?}
?? ?}
?
?? ?public static void main(String[] args) {
?? ??? ?MyClient clien = new MyClient();
?? ??? ?clien.setSize(200, 200); // 窗体大小
?? ??? ?clien.setVisible(true); // 显示窗体
?? ??? ?clien.connect(); // 连接服务器
?? ?}
}21.3——UDP程序
用户数据报协议(UDP) 是网络信息传输的另一种形式。基于 UDP 的通信和基于 TCP 的通信不同,基于 UDP的信息传递更快,但不提供可靠性保证。使用 UDP 传递数据时,用户无法知道数据能否正确地到达主机,也不能确定到达目的地的顺序是否和发送的顺序相同。虽然 UDP 是一种不可靠的协议,但如果需要较快地传输信息,并能容忍小的错误,可以考虑使用 UDP。

21.3.1——DatagramPacket类

第一种构造方法在创建 DatagramPacket 对象时,指定了数据包的内存空间和大小。第二种构造方法不仅指定了数据包的内存空间和大小,还指定了数据包的目标地址和端口。在发送数据时,必须指定接收方的 Socket 地址和端口号,因此使用第二种构造方法可创建发送数据的 DatagramPacket对象?

第一种构造方法创建 DatagramSocket 对象,构造数据报套接字,并将其绑定到本地主机任何可用的端口上。第二种构造方法创建 DatagramSocket 对象,创建数据报套接字,并将其绑定到本地主机的指定端口上。第三种构造方法创建 DatagramSocket 对象,创建数据报套接字,并将其绑定到指定的端口和指定的本地地址上。第三种构造函数适用于有多块网卡和多个IP 地址的情况。
如果接收数据时必须指定一个端口号,不允许系统随机产生,此时可以使用第二种构造方法。比如有个朋友要你给他写信,那他的地址就必须确定,不确定是不行的。在发送数据时通常使用第一种构造方法,不指定端口号,而是系统为我们分配一个端口号,就像寄信不需要到指定的邮局去寄一样
21.3.2——DatagramSocket类

21.3.3——UDP网络程序设计
根据前面所讲的网络编程的基本知识以及 UDP 网络编程的特点,下面创建一个广播数据报程序广播数据报是一项较新的技术,其原理类似于电台广播。广播电台需要在指定的波段和频率上广播信息,收听者也要将收音机调到指定的波段、频率,才可以收听广播内容

例题3
1
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
?
public class Notification extends Thread{
?? ?String weather ="dc开业,重新准备回家";?? ?//发送信息
?? ?int port =9898;
?? ?InetAddress iaddress =null;
?? ?MulticastSocket socket = null;?? ?//多点广播套接字
?? ?
?? ?Notification(){
?? ??? ?try {
?? ??? ??? ?iaddress =InetAddress.getByName("224.255.10.0");
?? ??? ??? ?socket = new MulticastSocket(port);
?? ??? ??? ?socket.setTimeToLive(1);
?? ??? ??? ?socket.joinGroup(iaddress);
?? ??? ?}catch(IOException e) {
?? ??? ??? ?e.printStackTrace();
?? ??? ?}
?? ?}
?? ?public void run() {
?? ??? ?while(true) {
?? ??? ??? ?DatagramPacket packet = null;
?? ??? ??? ?byte data[] = weather.getBytes();
?? ??? ??? ?packet = new DatagramPacket(data,data.length,port);
?? ??? ??? ?System.out.println(weather);
?? ??? ??? ?try {
?? ??? ??? ??? ?socket.send(packet);
?? ??? ??? ??? ?sleep(3000);
?? ??? ??? ?}catch(IOException e) {
?? ??? ??? ??? ?e.printStackTrace();
?? ??? ??? ?}catch(InterruptedException e) {
?? ??? ??? ??? ?e.printStackTrace();
?? ??? ??? ?}
?? ??? ?}
?? ?}
?? ?public static void main(String[] args) {
?? ??? ?Notification w= new Notification();
?? ??? ?w.start();
?? ?}
}

文章来源:https://blog.csdn.net/2202_75816395/article/details/134954224
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。