16岁做分期网站,天津建站软件,刮奖网站,北京互联网公司排名100强文章目录 7.1 网络基础和 Java 中的网络 - 揭开神秘的面纱7.1.1 基础知识7.1.2 重点案例#xff1a;实现一个简单的聊天程序7.1.3 拓展案例 1#xff1a;使用 UDP 进行消息广播7.1.4 拓展案例 2#xff1a;建立一个简单的 Web 服务器 7.2 创建客户端和服务器 - 构建沟通的桥… 文章目录 7.1 网络基础和 Java 中的网络 - 揭开神秘的面纱7.1.1 基础知识7.1.2 重点案例实现一个简单的聊天程序7.1.3 拓展案例 1使用 UDP 进行消息广播7.1.4 拓展案例 2建立一个简单的 Web 服务器 7.2 创建客户端和服务器 - 构建沟通的桥梁7.2.1 基础知识7.2.2 重点案例实现文件传输系统7.2.3 拓展案例 1构建简单的聊天应用7.2.4 拓展案例 2多客户端支持的服务器 7.3 高效网络编程技巧 - 提升你的网络魔法效率7.3.1 基础知识7.3.2 重点案例基于 NIO 的聊天服务器7.3.3 拓展案例 1使用线程池处理 Socket 连接7.3.4 拓展案例 2优化长连接的性能 7.1 网络基础和 Java 中的网络 - 揭开神秘的面纱
在这个章节我们将像是揭开一个神秘世界的面纱探索网络通信的基础知识并了解如何在Java中应用这些知识来建立连接和进行数据交换。
7.1.1 基础知识 IP地址每台连接到网络的设备都有一个唯一的IP地址用于标识设备在网络上的位置类似于现实世界中的邮寄地址。 端口号端口号用于标识设备上的特定程序允许一个IP地址提供多种不同的服务。想象一下一个大楼IP地址有多扇门端口号每扇门后都是不同的服务。 TCP和UDPTCP传输控制协议提供了一种可靠的数据传输方式确保数据完整无误地从源传到目的地而UDP用户数据报协议则是一种简单的协议不保证数据的可靠传输但在某些情况下能提供更快的数据传输速度。 Socket编程Socket是网络编程的基石提供了建立TCP连接和数据传输的方法。在Java中通过java.net包中的Socket类和ServerSocket类我们可以轻松实现网络通信。
7.1.2 重点案例实现一个简单的聊天程序
我们将创建一个简单的聊天程序其中包含一个服务器和一个客户端演示基于TCP的Socket通信。
服务器端:
import java.io.*;
import java.net.*;public class ChatServer {public static void main(String[] args) throws IOException {ServerSocket serverSocket new ServerSocket(5555);System.out.println(Server is waiting for client...);Socket clientSocket serverSocket.accept();PrintWriter out new PrintWriter(clientSocket.getOutputStream(), true);BufferedReader in new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));String inputLine;while ((inputLine in.readLine()) ! null) {System.out.println(Client says: inputLine);out.println(Echo: inputLine);}}
}客户端:
import java.io.*;
import java.net.*;public class ChatClient {public static void main(String[] args) throws IOException {Socket socket new Socket(localhost, 5555);PrintWriter out new PrintWriter(socket.getOutputStream(), true);BufferedReader in new BufferedReader(new InputStreamReader(socket.getInputStream()));BufferedReader stdIn new BufferedReader(new InputStreamReader(System.in));String userInput;while ((userInput stdIn.readLine()) ! null) {out.println(userInput);System.out.println(Server response: in.readLine());}}
}7.1.3 拓展案例 1使用 UDP 进行消息广播
除了TCP我们还可以使用UDP进行数据传输。下面是一个简单的使用UDP进行消息广播的示例。
广播消息:
import java.net.*;public class UdpBroadcast {public static void main(String[] args) throws IOException {DatagramSocket socket new DatagramSocket();byte[] buf Hello, UDP!.getBytes();InetAddress address InetAddress.getByName(255.255.255.255);DatagramPacket packet new DatagramPacket(buf, buf.length, address, 4445);socket.send(packet);socket.close();}
}7.1.4 拓展案例 2建立一个简单的 Web 服务器
使用Java的ServerSocket我们可以建立一个简单的Web服务器响应HTTP请求。
import java.io.*;
import java.net.*;public class SimpleWebServer {public static void main(String[] args) throws IOException {ServerSocket serverSocket new ServerSocket(8080);while (true) {Socket clientSocket serverSocket.accept();PrintWriter out new PrintWriter(clientSocket.getOutputStream(), true);out.println(HTTP/1.1 200 OK);out.println(Content-Type: text/html);out.println(\r\n);out.println(h1Hello, World!/h1);clientSocket.close();}}
}通过这些案例我们可以看到网络编程并不是什么遥不可及的技术。无论是实现基于TCP的聊天程序使用UDP进行数据广播还是建立一个简单的Web服务器Java都为我们提供了强大的工具。现在拿起你的工具开始在Java的网络世界中探险吧 7.2 创建客户端和服务器 - 构建沟通的桥梁
在Java网络编程的旅程中创建客户端和服务器是基本而关键的一步就像是在两座孤岛之间构建沟通的桥梁。客户端和服务器之间的交流基础是建立在网络协议之上的而TCP/IP协议是最常用的协议之一它能够确保数据的可靠传输。
7.2.1 基础知识 Socket在Java中Socket是实现网络通信的核心客户端通过Socket连接到服务器服务器接受客户端的连接请求来建立连接。 ServerSocket在服务器端ServerSocket用于监听来自客户端的连接请求。 TCP连接的建立客户端通过指定服务器的IP地址和端口号发起连接请求服务器监听到请求后通过接受请求来建立连接。
7.2.2 重点案例实现文件传输系统
假设我们要构建一个简单的文件传输系统允许客户端向服务器上传文件。
服务器端:
import java.io.*;
import java.net.*;public class FileTransferServer {public static void main(String[] args) throws IOException {ServerSocket serverSocket new ServerSocket(6666);System.out.println(Server is running and waiting for file...);Socket socket serverSocket.accept();DataInputStream dis new DataInputStream(socket.getInputStream());FileOutputStream fos new FileOutputStream(received_file.txt);byte[] buffer new byte[4096];int filesize 15123; // Send file size in separate msgint read 0;int totalRead 0;int remaining filesize;while((read dis.read(buffer, 0, Math.min(buffer.length, remaining))) 0) {totalRead read;remaining - read;System.out.println(read totalRead bytes.);fos.write(buffer, 0, read);}fos.close();dis.close();System.out.println(File received!);}
}客户端:
import java.io.*;
import java.net.*;public class FileTransferClient {public static void main(String[] args) throws IOException {Socket socket new Socket(localhost, 6666);FileInputStream fis new FileInputStream(to_send_file.txt);DataOutputStream dos new DataOutputStream(socket.getOutputStream());byte[] buffer new byte[4096];while (fis.read(buffer) 0) {dos.write(buffer);}fis.close();dos.close();System.out.println(File sent!);}
}7.2.3 拓展案例 1构建简单的聊天应用
我们可以通过Socket编程构建一个更实用的应用比如一个简单的聊天应用允许客户端和服务器互发消息。
聊天服务器
服务器端的任务是接受客户端连接并转发客户端发送的消息到所有其他已连接的客户端。
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.*;public class ChatServer {private static final int PORT 6666;private static final ListClientHandler clients new CopyOnWriteArrayList();private static ExecutorService pool Executors.newCachedThreadPool();public static void main(String[] args) throws IOException {ServerSocket serverSocket new ServerSocket(PORT);System.out.println(Chat Server is listening on port PORT);while (true) {Socket clientSocket serverSocket.accept();System.out.println(Accepted new connection from clientSocket);ClientHandler clientHandler new ClientHandler(clientSocket, clients);clients.add(clientHandler);pool.execute(clientHandler);}}
}class ClientHandler implements Runnable {private Socket clientSocket;private ListClientHandler clients;private PrintWriter out;private BufferedReader in;public ClientHandler(Socket socket, ListClientHandler clients) throws IOException {this.clientSocket socket;this.clients clients;this.out new PrintWriter(clientSocket.getOutputStream(), true);this.in new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));}Overridepublic void run() {try {String message;while ((message in.readLine()) ! null) {broadcastMessage(message);}} catch (IOException e) {System.out.println(Error in ClientHandler: e.getMessage());} finally {try {in.close();out.close();clientSocket.close();} catch (IOException e) {e.printStackTrace();}}}private void broadcastMessage(String message) {for (ClientHandler aClient : clients) {if (aClient ! this) {aClient.out.println(message);}}}
}聊天客户端
客户端的任务是连接到服务器发送自己的消息并接收从服务器转发的其他客户端的消息。
import java.io.*;
import java.net.*;public class ChatClient {private static final String SERVER_IP 127.0.0.1;private static final int SERVER_PORT 6666;public static void main(String[] args) throws IOException {Socket socket new Socket(SERVER_IP, SERVER_PORT);BufferedReader keyboardInput new BufferedReader(new InputStreamReader(System.in));PrintWriter out new PrintWriter(socket.getOutputStream(), true);BufferedReader in new BufferedReader(new InputStreamReader(socket.getInputStream()));// Create a new thread to read messages from the servernew Thread(new Runnable() {public void run() {try {String serverMessage;while ((serverMessage in.readLine()) ! null) {System.out.println(Server says: serverMessage);}} catch (IOException e) {System.out.println(Connection to server broken.);}}}).start();// Read messages from the keyboard and send them to the serverSystem.out.println(Enter your message: );String userInput;while ((userInput keyboardInput.readLine()) ! null) {out.println(userInput);}}
}在这个聊天应用中服务器能够接收多个客户端连接并将任一客户端发来的消息广播给所有其他客户端。客户端可以发送消息给服务器服务器则将这些消息转发给所有其他已连接的客户端。这样就实现了一个基础的多人聊天室功能。
7.2.4 拓展案例 2多客户端支持的服务器
要让服务器能够同时处理多个客户端我们可以为每个连接创建一个新的线程来处理。
服务器端:
public class MultiClientServer {public static void main(String[] args) throws IOException {ServerSocket serverSocket new ServerSocket(6666);System.out.println(Server is running...);while (true) {Socket socket serverSocket.accept();new Thread(new ClientHandler(socket)).start();}}
}class ClientHandler implements Runnable {private Socket socket;public ClientHandler(Socket socket) {this.socket socket;}Overridepublic void run() {// 处理客户端请求}
}通过实现这些案例你已经学会了如何在Java中创建客户端和服务器以及如何通过Socket进行基本的网络通信。无论是实现文件传输系统、构建简单的聊天应用还是支持多客户端的服务器这些基础知识都将为你打开网络编程的大门帮助你构建更复杂和强大的网络应用。 7.3 高效网络编程技巧 - 提升你的网络魔法效率
在Java网络编程的世界中掌握一些高效的技巧可以大大提升你的应用性能和用户体验。就像一个熟练的魔法师通过精细的魔法控制和策略可以在战斗中取得压倒性的胜利。让我们一起探索如何成为网络编程领域的高级魔法师。
7.3.1 基础知识 非阻塞I/ONIOJava NIO是一种基于通道(Channel)和缓冲区(Buffer)的I/O方式它可以让你非阻塞地读写数据提升I/O操作的效率。 I/O多路复用这是一种允许单个线程同时监控多个I/O通道的技术如果某个通道准备好了I/O操作系统就会通知线程。这减少了线程的数量和上下文切换的开销。 线程池使用线程池可以避免为每个请求创建新线程的开销复用线程资源提高应用性能。 连接池网络应用中频繁地建立和关闭连接会造成资源的浪费使用连接池可以复用已经建立的连接。
7.3.2 重点案例基于 NIO 的聊天服务器
我们将构建一个基于Java NIO的聊天服务器这个服务器可以非阻塞地处理多个客户端的连接和消息传输。
聊天服务器:
import java.nio.*;
import java.nio.channels.*;
import java.net.*;
import java.util.*;public class ChatServer {public void startServer() throws IOException {Selector selector Selector.open();ServerSocketChannel serverChannel ServerSocketChannel.open();serverChannel.bind(new InetSocketAddress(5555));serverChannel.configureBlocking(false);serverChannel.register(selector, SelectionKey.OP_ACCEPT);while (true) {selector.select(); // 阻塞直到至少有一个通道在你注册的事件上就绪了SetSelectionKey selectedKeys selector.selectedKeys();IteratorSelectionKey iter selectedKeys.iterator();while (iter.hasNext()) {SelectionKey key iter.next();if (key.isAcceptable()) {register(selector, serverChannel);}if (key.isReadable()) {broadcast(selector, key);}iter.remove();}}}private void register(Selector selector, ServerSocketChannel serverChannel) throws IOException {SocketChannel client serverChannel.accept();client.configureBlocking(false);client.register(selector, SelectionKey.OP_READ);}private void broadcast(Selector selector, SelectionKey key) throws IOException {SocketChannel client (SocketChannel) key.channel();ByteBuffer buffer ByteBuffer.allocate(256);client.read(buffer);String message new String(buffer.array()).trim();for (SelectionKey k : selector.keys()) {Channel target k.channel();if (target instanceof SocketChannel target ! client) {((SocketChannel) target).write(ByteBuffer.wrap(message.getBytes()));}}}public static void main(String[] args) throws IOException {new ChatServer().startServer();}
}7.3.3 拓展案例 1使用线程池处理 Socket 连接
在多用户网络应用中使用线程池来处理Socket连接可以大大提升性能。
import java.net.*;
import java.util.concurrent.*;public class ThreadPoolEchoServer {private static final int PORT 5555;private static final ExecutorService pool Executors.newFixedThreadPool(10);public static void main(String[] args) throws IOException {ServerSocket serverSocket new ServerSocket(PORT);System.out.println(Echo server is running.);while (true) {Socket clientSocket serverSocket.accept();pool.execute(new EchoClientHandler(clientSocket));}}
}class EchoClientHandler implements Runnable {private Socket clientSocket;public EchoClientHandler(Socket socket) {this.clientSocket socket;}Overridepublic void run() {// 处理客户端请求}
}7.3.4 拓展案例 2优化长连接的性能
在需要维护长时间连接的应用中合理管理这些连接是提升性能的关键。
优化长连接的性能是网络编程中的一个常见需求尤其是在需要维护与客户端持续交互的应用中。以下是一个使用Java实现的简单心跳机制和连接池管理来优化长连接性能的示例。
**心跳机制**心跳机制Heartbeat用于维持客户端与服务器之间的长连接通过定期发送轻量级的心跳消息来确认连接的活性。
服务器端示例:
import java.io.*;
import java.net.*;
import java.util.concurrent.*;public class HeartbeatServer {private static final int PORT 5555;private static final ExecutorService pool Executors.newCachedThreadPool();public static void main(String[] args) throws IOException {ServerSocket serverSocket new ServerSocket(PORT);System.out.println(Server started, waiting for connections...);while (true) {Socket clientSocket serverSocket.accept();pool.execute(new ClientHandler(clientSocket));}}static class ClientHandler implements Runnable {private final Socket clientSocket;public ClientHandler(Socket socket) {this.clientSocket socket;}Overridepublic void run() {try (DataInputStream dis new DataInputStream(clientSocket.getInputStream());DataOutputStream dos new DataOutputStream(clientSocket.getOutputStream())) {while (true) {String message dis.readUTF(); // Read heartbeat messageif (HEARTBEAT.equals(message)) {dos.writeUTF(ACK); // Acknowledge heartbeat} else {// Handle other messages}}} catch (IOException e) {System.out.println(Client disconnected.);}}}
}客户端示例:
import java.io.*;
import java.net.*;public class HeartbeatClient {public static void main(String[] args) {try (Socket socket new Socket(localhost, 5555);DataOutputStream dos new DataOutputStream(socket.getOutputStream());DataInputStream dis new DataInputStream(socket.getInputStream())) {while (true) {dos.writeUTF(HEARTBEAT); // Send heartbeat messageString response dis.readUTF(); // Wait for server acknowledgmentif (ACK.equals(response)) {System.out.println(Heartbeat acknowledged by server.);}Thread.sleep(5000); // Send heartbeat every 5 seconds}} catch (IOException | InterruptedException e) {System.out.println(Error: e.getMessage());}}
}连接池管理
在需要维护多个长连接时使用连接池可以提高资源的复用率和应用性能。虽然Java标准库中没有直接支持连接池的API但我们可以通过第三方库如Apache Commons Pool或HikariCP来实现连接池管理。以下是概念性描述具体实现将依赖于选用的连接池库
// 创建连接池配置
HikariConfig config new HikariConfig();
config.setJdbcUrl(jdbc:mysql://localhost:3306/yourdatabase);
config.setUsername(user);
config.setPassword(password);
config.addDataSourceProperty(cachePrepStmts, true);
config.addDataSourceProperty(prepStmtCacheSize, 250);
config.addDataSourceProperty(prepStmtCacheSqlLimit, 2048);// 实例化连接池
HikariDataSource dataSource new HikariDataSource(config);// 使用连接池获取连接
try (Connection conn dataSource.getConnection();PreparedStatement stmt conn.prepareStatement(your SQL query)) {// 处理数据库操作
} catch (SQLException e) {// 异常处理
}通过这些技术你可以有效地管理长连接提升应用的性能和稳定性。心跳机制确保连接的活性而连接池管理则提高了资源的利用率和响应速度。这些高级技巧将在网络编程中赋予你更大的力量和灵活性。