跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C

Linux 网络编程基础:套接字

介绍 Linux 下网络编程中的套接字(Socket)概念。对比了 UDP 和 TCP 协议的特性,包括连接性、可靠性及适用场景。详细讲解了 sockaddr 结构体及其派生类,字节序转换接口(htons/htonl 等)。重点阐述了 socket、bind、sendto、recvfrom 等 UDP 接口,以及 listen、accept、connect 等 TCP 接口。最后提供了基于 C 语言的 UDP 和 TCP 客户端服务端通信代码示例,涵盖创建套接字、绑定端口、收发数据等完整流程。

星辰大海发布于 2026/3/28更新于 2026/7/2350 浏览
Linux 网络编程基础:套接字

一、套接字基本概念

套接字(Socket)是计算机网络中用于进程间通信的一种机制,通常用于不同主机之间的数据传输。它抽象了底层网络协议的细节,为应用程序提供统一的接口。套接字是 IP 地址与端口号的组合,用于唯一标识网络中的一个通信端点。

二、套接字工作原理

套接字通过绑定特定的 IP 地址和端口号,实现数据的发送和接收。通信双方各自创建一个套接字,并通过网络协议(如 TCP 或 UDP)建立连接。数据通过套接字进行传输,发送方将数据写入套接字,接收方从套接字读取数据。

三、协议认识-UDP/TCP

UDP 和 TCP 特点

特性TCP(传输控制协议)UDP(用户数据报协议)
连接性面向连接(三次握手建立连接,四次挥手断开)无连接(无需握手,直接发数据)
可靠性可靠传输(保证数据不丢、不重、有序到达)不可靠传输(不保证送达,可能丢包 / 乱序)
有序性保证数据按发送顺序到达(有序列号机制)不保证有序(先发的可能后到)
重传机制丢包会重传(超时重传、快速重传)无重传(丢包就丢了,不处理)
流量控制有(滑动窗口机制,避免发送方发太快压垮接收方)无(发送方只管发,不管接收方能不能处理)
拥塞控制有(慢启动、拥塞避免等,适配网络拥堵)无(网络再堵也照常发)
数据边界无(流式数据,比如发 2 次 10 字节,接收可能一次收 20 字节)有(数据报边界,发 1 次 10 字节,接收只能收 10 字节)
开销高(头部 20~60 字节,加握手 / 重传 / 控流等逻辑)低(头部仅 8 字节,无额外控制逻辑)
速度慢(可靠性和控流导致延迟高)快(无额外开销,延迟低)
适用场景对可靠性要求高的场景对速度 / 实时性要求高的场景
前置:sockaddr 结构体
struct sockaddr {
    unsigned short sa_family; // 地址族(如 AF_INET、AF_INET6)
    char sa_data[14];         // 协议特定的地址信息
};
/* sa_family:指定地址族,常见值包括:
 *   AF_INET:IPv4 地址。
 *   AF_INET6:IPv6 地址。
 *   AF_UNIX:Unix 域套接字。
 * sa_data:存储具体的地址和端口信息,格式由协议族决定。
 */

sockaddr 是网络编程中用于表示套接字地址的通用结构体,定义在 <sys/socket.h> 头文件中。它通常用于存储 IP 地址和端口信息,支持多种协议族(如 IPv4、IPv6 等)。

结构体常见派生类
sockaddr_in(IPv4)
struct sockaddr_in {
    short sin_family;     // 地址族(AF_INET)
    unsigned short sin_port; // 端口号(网络字节序)
    struct in_addr sin_addr; // IPv4 地址
    char sin_zero[8];      // 填充字段(未使用)
}; 
sockaddr_in6(IPv6)
struct sockaddr_in6 {
    unsigned short sin6_family; // 地址族(AF_INET6)
    unsigned short sin6_port;   // 端口号(网络字节序)
    unsigned long sin6_flowinfo; // 流信息
    struct in6_addr sin6_addr;   // IPv6 地址
    unsigned int sin6_scope_id;  // 作用域 ID
}; 
注意事项
  • 字节序:端口和 IP 地址需转换为网络字节序(大端)。
  • 地址族匹配:确保 sa_family 与使用的套接字类型一致。
  • 通用性:sockaddr 设计为通用结构体,实际使用时应优先选择具体的派生结构体。

UDP

相关接口认识

UDP 作为无连接、轻量级的传输层协议,其编程接口相比 TCP 更简洁,核心就是 socket()、bind()、sendto()、recvfrom() 四个接口。

1. 字节序转换核心接口(htons/htonl/ntohs/ntohl)
功能定位

网络协议规定所有传输的多字节数据(如端口、32 位 IP 整数)必须使用网络字节序(大端序),而不同机器的本地字节序可能是小端(主流)或大端,因此在绑定 / 指定地址时,必须通过这些接口完成本地序 ↔ 网络序的转换,否则会出现端口 / IP 解析错误。

接口说明
  • uint16_t htons(uint16_t hostshort):Host to Network Short,将 16 位本地序端口号转为网络序(UDP/TCP 端口都是 16 位,必用);
  • uint32_t htonl(uint32_t hostlong):Host to Network Long,将 32 位本地序 IP 整数转为网络序(如 INADDR_ANY 转换);
  • uint16_t ntohs(uint16_t netshort):Network to Host Short,将 16 位网络序端口号转回本地序(接收数据后解析端口时用);
  • uint32_t ntohl(uint32_t netlong):Network to Host Long,将 32 位网络序 IP 整数转回本地序(极少用,通常用 inet_ntop 直接转字符串)。
核心使用场景
  • 绑定端口:local_addr.sin_port = htons(8080);
  • 指定目标端口:server_addr.sin_port = htons(8080);
  • 绑定所有网卡:local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  • 解析接收的客户端端口:ntohs(client_addr.sin_port);
2. int socket(int domain, int type, int protocol);
功能定位

这是网络编程的第一步,作用是创建一个套接字描述符(简称 sockfd),相当于给程序分配一个专属的'通信管道',后续所有的发送、接收操作都要基于这个 fd 完成。

参数解读
  • domain:指定通信使用的地址族,决定网络协议版本。日常开发中最常用的是 AF_INET(对应 IPv4 协议),如果需要支持 IPv6 则用 AF_INET6。
  • type:指定套接字的通信类型,UDP 必须用 SOCK_DGRAM(数据报类型),这个参数直接决定了通信是无连接、有数据边界的 UDP 模式;如果填 SOCK_STREAM 则是 TCP 模式。
  • protocol:指定具体的传输协议,通常填 0 即可 —— 系统会根据前面的 type 参数自动匹配对应的协议(比如 SOCK_DGRAM 对应 UDP,SOCK_STREAM 对应 TCP),无需手动指定 IPPROTO_UDP 或 IPPROTO_TCP。
返回值

成功时返回一个非负整数(就是套接字 fd,可理解为'管道编号');失败时返回 -1,此时可以用 perror("socket") 打印具体的错误原因,比如权限不足、参数填错等。

3. int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能定位

把创建好的套接字 fd 绑定到本地的 IP 地址和端口号上。对 UDP 来说,服务端必须调用 bind 绑定固定端口(比如 8080),否则客户端无法找到对应的服务端;客户端则可选调用 —— 如果不绑定,系统会在发送数据时自动分配一个随机端口。

参数解读
  • sockfd:要绑定的套接字 fd,必须是 socket() 调用成功返回的有效 fd,且未被关闭。
  • addr:指向存储本地地址信息的结构体,虽然参数类型是通用的 struct sockaddr,但实际开发中我们会用更贴合 IPv4 的 struct sockaddr_in 结构体,传参时强转为 struct sockaddr* 即可。这个结构体需要提前初始化,包括地址族(和 socket() 的 domain 一致)、端口号(必须转网络序)、IP 地址(通常填 INADDR_ANY 表示绑定本机所有网卡,一般不进行手动绑定特定 IP)。
  • addrlen:地址结构体的长度,直接填 sizeof(struct sockaddr_in) 就能满足 IPv4 场景的需求。
4. ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
功能定位

UDP 最核心的发送接口,作用是把缓冲区里的数据发送到指定的目标地址(对方的 IP + 端口)。因为 UDP 是无连接的,所以每次发送都需要明确指定目标地址,这也是它和 TCP 的 send() 最核心的区别。

参数解读
  • sockfd:发送数据用的套接字 fd,需是有效且未关闭的。
  • buf:指向要发送的数据缓冲区,比如存储字符串、字节数组的内存地址,这个参数是只读的,函数不会修改缓冲区内容。
  • len:要发送的数据长度,单位是字节,比如发送字符串时可用 strlen(buf),发送字节数组则填数组的实际长度。
  • flags:发送标志位,日常开发中填 0 即可(表示阻塞发送,直到数据发出或出错);如果需要非阻塞发送,可填 MSG_DONTWAIT,但新手建议先掌握默认的阻塞模式。
  • dest_addr:指向目标地址的结构体,和 bind() 的 addr 类似,需提前初始化对方的 IP 地址和端口号(端口同样要转网络序)。
  • addrlen:目标地址结构体的长度,填 sizeof(struct sockaddr_in) 即可。
返回值

成功时返回实际发送的字节数(UDP 特性:要么发送全部数据,要么失败,不会出现发送部分数据的情况);失败时返回 -1,常见错误有网络不可达、目标地址错误、fd 无效等。

5. ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
功能定位

UDP 核心的接收接口,作用是从套接字中读取接收到的数据,同时获取发送方的地址(IP + 端口)—— 这也是 UDP 无连接特性的体现:接收数据时才知道数据是谁发的。

参数解读
  • sockfd:接收数据用的套接字 fd,需是有效且绑定了端口的(服务端必须 bind,客户端若未 bind 则系统自动分配端口)。
  • buf:指向存储接收数据的缓冲区,函数会把接收到的数据写入这个缓冲区,需提前分配足够的内存(比如定义 char buf[1024])。
  • len:缓冲区的最大长度,避免数据溢出,比如 sizeof(buf)。
  • flags:接收标志位,默认填 0(阻塞接收,直到有数据到来);MSG_DONTWAIT 同样用于非阻塞接收。
  • src_addr:指向存储发送方地址的结构体,调用后会自动填充对方的 IP 和端口,方便后续回复数据。
  • addrlen:传入传出参数,调用前要初始化为地址结构体的长度(比如 sizeof(struct sockaddr_in)),函数会根据实际地址长度修改这个值,因此必须传指针。
返回值

成功时返回实际接收的字节数;失败时返回 -1,常见错误有 fd 被关闭、缓冲区过小(但不会溢出,只会截断数据)等;如果是非阻塞模式,无数据时也会返回 -1,需结合 errno 判断。

UDP 套接字创建流程-client-server 通信实现

创建 UDP 套接字实现网络通信的步骤简单并且公式化

server 端:创建套接字->绑定端口->循环收取数据

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 8888
#define BUF_LEN 1024

int main() {
    // 1. 创建 UDP 套接字:socket(AF_INET, SOCK_DGRAM, 0)
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    
    // 2. 绑定地址:bind(sockfd, &addr, sizeof(addr))
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 网络序转换:htonl()
    serv_addr.sin_port = htons(PORT);              // 网络序转换:htons()
    bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
    
    // 3. 接收数据:recvfrom(sockfd, buf, len, 0, &cli_addr, &len)
    char buf[BUF_LEN];
    struct sockaddr_in cli_addr;
    socklen_t cli_len = sizeof(cli_addr);
    while (1) {
        int n = recvfrom(sockfd, buf, BUF_LEN, 0, (struct sockaddr*)&cli_addr, &cli_len);
        buf[n] = '\0';
        printf("收到客户端 [%s:%d]:%s\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port), buf);
    }
    close(sockfd);
    return 0;
}

client 端:创建套接字->指定服务端 IP->发送数据

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define SERV_IP "127.0.0.1"
#define SERV_PORT 8888
#define BUF_LEN 1024

int main() {
    // 1. 创建 UDP 套接字:socket(AF_INET, SOCK_DGRAM, 0)
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    
    // 2. 配置服务端地址
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr(SERV_IP);
    serv_addr.sin_port = htons(SERV_PORT); // 网络序转换:htons()
    
    // 3. 发送数据:sendto(sockfd, buf, len, 0, &serv_addr, sizeof(addr))
    char buf[BUF_LEN] = "Hello UDP Server!";
    sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
    printf("已发送:%s\n", buf);
    close(sockfd);
    return 0;
}

TCP

相关接口认识

TCP 作为面向连接、可靠的传输层协议,其编程接口相比 UDP 更复杂,核心新增接口包含 listen ()、accept ()、connect ()、send ()、recv (),基础的 socket ()、bind () 及字节序转换接口与 UDP 通用(不再重复)。

1. int listen(int sockfd, int backlog);
功能定位

服务端调用,将已绑定的套接字从'主动态'转为'被动态',使其监听客户端的连接请求。TCP 是面向连接的协议,服务端必须先监听端口,才能接收客户端的连接。

参数解读
  • sockfd:已绑定地址的套接字 fd(由 socket() 创建、bind() 绑定);
  • backlog:指定内核为该套接字维护的'未完成连接队列 + 已完成连接队列'的最大长度(如 5、10),超出的连接请求会被拒绝,新手填 5 即可满足基础场景。
返回值

成功返回 0;失败返回 -1,可通过 perror("listen") 排查错误(如 fd 未绑定、参数非法)。

2. int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能定位

服务端阻塞等待客户端的连接请求,当有客户端发起连接(三次握手完成),会创建一个新的套接字 fd 用于与该客户端通信,原监听 fd 继续监听其他客户端。

参数解读
  • sockfd:监听状态的套接字 fd(listen() 调用后的 fd);
  • addr:指向存储客户端地址信息的结构体,调用后会自动填充客户端的 IP 和端口,可传 NULL 表示不关心客户端地址;
  • addrlen:传入传出参数,调用前初始化为地址结构体长度(sizeof(struct sockaddr_in)),调用后会更新为实际地址长度,必须传指针。
返回值

成功返回新的通信套接字 fd(用于和该客户端收发数据);失败返回 -1(如 fd 未监听、被信号中断)。

3. int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能定位

客户端调用,主动向服务端发起 TCP 连接(触发三次握手)。只有连接建立成功后,才能通过该套接字收发数据。

参数解读
  • sockfd:客户端创建的套接字 fd(socket() 返回);
  • addr:指向服务端地址结构体,需初始化服务端的 IP 和端口(端口转网络序);
  • addrlen:服务端地址结构体的长度(sizeof(struct sockaddr_in))。
返回值

成功返回 0(三次握手完成,连接建立);失败返回 -1(如服务端未监听、网络不可达、端口错误)。

4. ssize_t send(int sockfd, const void *buf, size_t len, int flags);
功能定位

TCP 核心发送接口,向已建立连接的对端发送数据。因 TCP 是流式协议,send() 可能返回小于 len 的值(如内核缓冲区满),需循环发送确保数据全部发出。

参数解读

  • sockfd:已建立连接的通信套接字 fd(客户端 connect() 成功后的 fd、服务端 accept() 返回的新 fd);
  • buf:要发送的数据缓冲区(只读);
  • len:要发送的数据长度(字节);
  • flags:默认填 0(阻塞发送),与 UDP sendto() 的 flags 用法一致(如 MSG_DONTWAIT 为非阻塞)。
返回值

成功返回实际发送的字节数(可能小于 len);失败返回 -1(如连接断开、fd 无效)。

5. ssize_t recv(int sockfd, void *buf, size_t len, int flags);
功能定位

TCP 核心接收接口,从已建立连接的套接字中读取数据。因 TCP 是流式无边界协议,recv() 读取的字节数可能小于缓冲区长度,需循环读取直到获取完整数据。

参数解读
  • sockfd:已建立连接的通信套接字 fd;
  • buf:存储接收数据的缓冲区;
  • len:缓冲区最大长度(避免溢出);
  • flags:默认填 0(阻塞接收),无数据时会阻塞等待。
返回值

成功返回实际接收的字节数;返回 0 表示对端关闭连接(四次挥手完成);失败返回 -1(如连接中断、fd 无效)。

TCP 套接字创建流程-client-server 通信实现

TCP 通信需遵循'服务端监听→客户端连接→双向收发'的固定流程,核心是三次握手建立连接、基于新 fd 通信。

server 端:创建套接字→绑定端口→监听端口→接受连接→循环接收数据

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 8888
#define BUF_LEN 1024

int main() {
    // 创建 TCP 套接字
    int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    
    // 绑定地址
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(PORT);
    bind(listen_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
    
    // 监听端口
    listen(listen_fd, 5);
    
    // 接受连接
    struct sockaddr_in cli_addr;
    socklen_t cli_len = sizeof(cli_addr);
    int conn_fd = accept(listen_fd, (struct sockaddr*)&cli_addr, &cli_len);
    printf("客户端 [%s:%d] 已连接\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));
    
    // 接收数据
    char buf[BUF_LEN];
    while (1) {
        int n = recv(conn_fd, buf, BUF_LEN-1, 0);
        if (n <= 0) {
            printf("客户端断开连接\n");
            break;
        }
        buf[n] = '\0';
        printf("收到客户端:%s\n", buf);
    }
    close(conn_fd);
    close(listen_fd);
    return 0;
}

client 端:创建套接字→连接服务端→发送数据

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define SERV_IP "127.0.0.1"
#define SERV_PORT 8888
#define BUF_LEN 1024

int main() {
    // 创建 TCP 套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    
    // 连接服务端
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr(SERV_IP);
    serv_addr.sin_port = htons(SERV_PORT);
    connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
    
    // 发送数据
    char buf[BUF_LEN] = "Hello TCP Server!";
    send(sockfd, buf, strlen(buf), 0);
    printf("已发送:%s\n", buf);
    close(sockfd);
    return 0;
}

目录

  1. 一、套接字基本概念
  2. 二、套接字工作原理
  3. 三、协议认识-UDP/TCP
  4. UDP 和 TCP 特点
  5. 前置:sockaddr 结构体
  6. 结构体常见派生类
  7. sockaddr_in(IPv4)
  8. sockaddr_in6(IPv6)
  9. 注意事项
  10. UDP
  11. 相关接口认识
  12. 1. 字节序转换核心接口(htons/htonl/ntohs/ntohl)
  13. 功能定位
  14. 接口说明
  15. 核心使用场景
  16. 2. int socket(int domain, int type, int protocol);
  17. 功能定位
  18. 参数解读
  19. 返回值
  20. 3. int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  21. 功能定位
  22. 参数解读
  23. 4. ssizet sendto(int sockfd, const void buf, sizet len, int flags, const struct sockaddr destaddr, socklent addrlen);
  24. 功能定位
  25. 参数解读
  26. 返回值
  27. 5. ssizet recvfrom(int sockfd, void buf, sizet len, int flags, struct sockaddr srcaddr, socklent *addrlen);
  28. 功能定位
  29. 参数解读
  30. 返回值
  31. UDP 套接字创建流程-client-server 通信实现
  32. TCP
  33. 相关接口认识
  34. 1. int listen(int sockfd, int backlog);
  35. 功能定位
  36. 参数解读
  37. 返回值
  38. 2. int accept(int sockfd, struct sockaddr addr, socklen_t addrlen);
  39. 功能定位
  40. 参数解读
  41. 返回值
  42. 3. int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  43. 功能定位
  44. 参数解读
  45. 返回值
  46. 4. ssizet send(int sockfd, const void *buf, sizet len, int flags);
  47. 功能定位
  48. 返回值
  49. 5. ssizet recv(int sockfd, void *buf, sizet len, int flags);
  50. 功能定位
  51. 参数解读
  52. 返回值
  53. TCP 套接字创建流程-client-server 通信实现
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • AIGC 产品经理面试 100 道高频问题及答案解析
  • 无人机视觉目标检测数据集 VisDrone 详解
  • C++ 进阶:AVL 树的原理与实现
  • 2025 WAIC 合合信息展台:AI 鉴伪技术洞察伪造痕迹
  • Linux 部署本地 AI 大模型与知识库集成指南
  • GESP C++ 七级真题解析:金币收集
  • OpenClaw 接入飞书实战:让 AI 机器人操作文档与表格
  • Web 应用架构与常见安全漏洞解析
  • Python 六种常见爬虫方法介绍
  • Ollama 本地大模型 WebAPI 调用实战指南
  • 如何降低 AIGC 检测率:15 个提示词优化写作风格
  • MySQL 用户查询方法详解
  • object-browser 核心功能解析:文件上传、版本控制与权限管理
  • Python 基础语法详解与实战练习
  • Flutter 与 Web 混合开发实践
  • Flask 框架从入门到实战完整指南
  • 为 GitHub Copilot 构建智能体记忆系统
  • Ubuntu 系统服务管理与 systemd 配置实战
  • 人工智能(AI)简介
  • Python 协同过滤算法 Django 餐厅推荐系统

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online