Socket(套接字)是网络通信中的一个关键概念,它是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。

一、定义与概念

  • 基本概念:Socket可以被视为网络环境中进程间通信的API(应用程序编程接口),也是可以被命名和寻址的通信端点。它是应用程序通过网络协议进行通信的接口,上联应用进程,下联网络协议栈。
  • 物理与逻辑层面:在物理层面上,Socket可能并不真实存在,它更多的是一个逻辑上的概念。但在网络编程中,Socket是不可或缺的组成部分。

二、功能与作用

  • 数据交换:Socket提供了应用层进程利用网络协议交换数据的机制。通过Socket,不同主机上的应用进程可以互相发送和接收数据。
  • 协议封装:Socket是对TCP/IP等网络协议的封装,它隐藏了复杂的网络协议细节,使得网络编程更加简单和直观。
  • 类型与连接:Socket一般分为TCP Socket和UDP Socket两种类型。TCP Socket提供面向连接、可靠的数据传输服务;而UDP Socket则提供无连接的数据传输服务。

三、工作原理

  • 服务器监听:服务器首先创建一个Socket,并绑定到指定的IP地址和端口上。然后,服务器进入监听状态,等待客户端的连接请求。
  • 客户端请求:客户端也创建一个Socket,并尝试连接到服务器的IP地址和端口上。如果连接成功,客户端和服务器之间就建立了一个通信通道。
  • 数据传输:建立连接后,客户端和服务器就可以通过Socket发送和接收数据了。在TCP连接中,数据会按照顺序、可靠地传输;而在UDP连接中,数据则可能会丢失或乱序到达。

四、应用场景

  • 客户端/服务器架构:在客户端/服务器架构中,Socket被广泛用于实现服务器端和客户端之间的通信。
  • 实时数据传输:Socket可用于实现实时数据传输,如视频流、音频流、实时游戏等。
  • 分布式系统:在分布式系统中,Socket可以被用于节点之间的消息传递和数据交换。
  • Web编程:在Web编程中,Socket可以用于实现WebSocket协议,以提供双向的实时通信。

五、Java Socket编程

Java中的Socket编程是网络编程的基础,它允许两个或多个程序通过网络进行通信。Socket编程在Java中通常涉及两种类型的Socket:ServerSocket和Socket。

5.1 ServerSocket

ServerSocket用于在服务器端监听来自客户端的连接请求。当一个连接被接受时,ServerSocket会返回一个Socket实例,这个实例代表了与客户端的连接,之后服务器端就可以通过这个Socket实例与客户端进行通信了。

创建ServerSocket的基本步骤如下:

  1. 创建ServerSocket实例:通过调用ServerSocket的构造器,并指定一个端口号(可选地,也可以指定一个IP地址,但通常指定为null,表示监听所有可用的网络接口)。
  2. 等待连接:通过调用ServerSocket的accept()方法等待客户端的连接。这个方法会阻塞,直到一个连接被建立。
  3. 通信:一旦accept()方法返回了一个Socket实例,就可以通过这个实例的输入流和输出流与客户端进行通信了。
  4. 关闭连接:通信结束后,需要关闭Socket和ServerSocket实例以释放资源。

5.2 Socket

Socket是网络通信的端点,它包含了进行网络通信所需的输入流和输出流。一个Socket实例可以是由ServerSocket的accept()方法返回,代表一个客户端连接;也可以是通过调用Socket的构造器创建的,表示主动向服务器发起连接请求的客户端。

创建客户端Socket的基本步骤如下:

  1. 创建Socket实例:通过调用Socket的构造器,并指定服务器的IP地址和端口号。
  2. 通信:一旦Socket实例被创建,就可以通过它的输入流和输出流与服务器进行通信了。
  3. 关闭连接:通信结束后,需要关闭Socket实例以释放资源。

六、示例

package org.example.socket;

import org.apache.commons.lang3.time.DateFormatUtils;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;

/**
 * Socket 服务端示例
 */
public class SocketServerDemo {
    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(8080);
            while(true) {
                Socket socket = serverSocket.accept();
                System.out.println("客户端连接成功!");
                System.out.println("对方端口号为:" + socket.getPort());

                //读取客户端写入内容
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String receiveContent = bufferedReader.readLine();
                System.out.println("服务端收到客户端信息:" + receiveContent + " 【" + DateFormatUtils.format(new Date(), "yyyyMMdd HH:mm:ss") + "】");
                System.out.println("3秒后,回复对方。");
                Thread.sleep(3000);
                //服务端回复客户端信息
                BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                bufferedWriter.write("你好,亲爱的客户端朋友!\n");
                bufferedWriter.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package org.example.socket;

import org.apache.commons.lang3.time.DateFormatUtils;

import java.io.*;
import java.net.Socket;
import java.util.Date;

/**
 * Socket 客户端示例
 */
public class SocketClient {
    public static void main(String[] args) {
        Socket socket = null;
        try {
            socket = new Socket("localhost",8080);

            BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            bufferedWriter.write("你好,尊敬的服务端先生!\n");
            bufferedWriter.flush();

            Thread.sleep(3000);

            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String acceptFromServer = bufferedReader.readLine();
            System.out.println("收到服务端回复:"+acceptFromServer+ " 【"+ DateFormatUtils.format(new Date(),"yyyyMMdd HH:mm:ss") +"】");
            bufferedReader.close();
            bufferedWriter.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

先执行服务端 main方法,ServerSocket阻塞;
然后执行客户端 main 方法,服务端与客户端相继输出如下内容:

服务端打印内容:

客户端连接成功!
对方端口号为:40057
服务端收到客户端信息:你好,尊敬的服务端先生! 【20240718 17:12:56】
3秒后,回复对方。

客户端打印内容:

收到服务端回复:你好,亲爱的客户端朋友! 【20240718 17:12:59】

七、总结

Socket是网络通信中的核心组件之一,它提供了应用层进程之间进行数据交换的机制。通过Socket,不同主机上的应用进程可以建立连接并传输数据。无论是客户端/服务器架构、实时数据传输还是分布式系统等领域,Socket都发挥着重要的作用。


以上就是 Socket 简介与 Java Socket 编程示例 全部内容,感谢阅读!

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐