Java 网络编程是使用 Java 编程语言进行网络通信的过程。其中,Socket 编程是 Java 中最基本的网络编程方式之一,它允许不同的计算机通过网络进行通信。

Socket 编程

Socket 是网络通信中的一个概念,它提供了一种通信机制,允许客户端和服务器之间进行数据交换。在 Java 中,可以使用 java.net.Socket 类和 java.net.ServerSocket 类来实现 Socket 编程。

  • 客户端 Socket:客户端 Socket 用于连接到服务器,并发送请求。可以使用 Socket 类来创建客户端 Socket。

    <div><p><code id="code-lang-java"><span>import</span> java.net.*;
    
    <span>public</span> <span>class</span> <span>Client</span> {
        <span>public</span> <span>static</span> <span>void</span> <span>main</span><span>(String[] args)</span> <span>throws</span> Exception {
            <span>Socket</span> <span>clientSocket</span> <span>=</span> <span>new</span> <span>Socket</span>(<span>"服务器IP"</span>, 服务器端口号);
            <span>// 在这里进行数据发送和接收</span>
            clientSocket.close(); <span>// 关闭客户端 Socket</span>
        }
    }
    </code></p></div>
    
  • 服务器 Socket:服务器 Socket 用于监听来自客户端的连接请求,并处理这些请求。可以使用 ServerSocket 类来创建服务器 Socket。

    <div><p><code id="code-lang-java"><span>import</span> java.net.*;
    
    <span>public</span> <span>class</span> <span>Server</span> {
        <span>public</span> <span>static</span> <span>void</span> <span>main</span><span>(String[] args)</span> <span>throws</span> Exception {
            <span>ServerSocket</span> <span>serverSocket</span> <span>=</span> <span>new</span> <span>ServerSocket</span>(服务器端口号);
            <span>while</span> (<span>true</span>) {
                <span>Socket</span> <span>connectionSocket</span> <span>=</span> serverSocket.accept(); <span>// 等待客户端连接</span>
                <span>// 在这里处理连接,并进行数据交换</span>
                connectionSocket.close(); <span>// 关闭与客户端的连接</span>
            }
        }
    }
    </code></p></div>
    

阻塞与非阻塞 IO

在网络编程中,I/O 操作是常见的。Java 提供了阻塞和非阻塞两种 I/O 模式。

  • 阻塞 IO:在阻塞模式下,当程序执行 I/O 操作时,程序将会被阻塞,直到操作完成或超时。阻塞模式下的 Socket 会一直等待数据的到来或者发送完成,期间不会执行其他任务。

  • 非阻塞 IO:在非阻塞模式下,当程序执行 I/O 操作时,如果数据没有准备好或者无法立即进行 I/O 操作,程序不会被阻塞,而是立即返回,让程序可以继续执行其他任务。可以通过设置 Socket 为非阻塞模式来实现非阻塞 IO。

Java 中的 java.nio 包提供了非阻塞 IO 的支持,通过 SelectorChannel 等类可以实现非阻塞 IO 操作。

<div><p><code id="code-lang-java"><span>import</span> java.nio.*;
<span>import</span> java.nio.channels.*;

<span>public</span> <span>class</span> <span>NonBlockingServer</span> {
    <span>public</span> <span>static</span> <span>void</span> <span>main</span><span>(String[] args)</span> <span>throws</span> Exception {
        <span>ServerSocketChannel</span> <span>serverSocketChannel</span> <span>=</span> ServerSocketChannel.open();
        serverSocketChannel.socket().bind(<span>new</span> <span>InetSocketAddress</span>(<span>"localhost"</span>, <span>8080</span>));
        serverSocketChannel.configureBlocking(<span>false</span>); <span>// 设置为非阻塞模式</span>

        <span>Selector</span> <span>selector</span> <span>=</span> Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        <span>while</span> (<span>true</span>) {
            <span>int</span> <span>readyChannels</span> <span>=</span> selector.select();
            <span>if</span> (readyChannels == <span>0</span>) <span>continue</span>;

            Set&lt;SelectionKey&gt; selectedKeys = selector.selectedKeys();
            Iterator&lt;SelectionKey&gt; keyIterator = selectedKeys.iterator();

            <span>while</span> (keyIterator.hasNext()) {
                <span>SelectionKey</span> <span>key</span> <span>=</span> keyIterator.next();

                <span>if</span> (key.isAcceptable()) {
                    <span>// 处理连接请求</span>
                    <span>ServerSocketChannel</span> <span>serverChannel</span> <span>=</span> (ServerSocketChannel) key.channel();
                    <span>SocketChannel</span> <span>clientChannel</span> <span>=</span> serverChannel.accept();
                    clientChannel.configureBlocking(<span>false</span>);
                    clientChannel.register(selector, SelectionKey.OP_READ);
                } <span>else</span> <span>if</span> (key.isReadable()) {
                    <span>// 处理读取数据</span>
                    <span>SocketChannel</span> <span>clientChannel</span> <span>=</span> (SocketChannel) key.channel();
                    <span>// 读取数据操作</span>
                }
                keyIterator.remove();
            }
        }
    }
}
</code></p></div>

以上是 Java 网络编程基础中 Socket 编程、阻塞与非阻塞 IO 的简单介绍和示例代码。