Socket(套接字)是网络编程的基石,它为不同主机上的进程间通信(IPC)提供了一个统一的编程接口。在 Linux 系统中,Socket 编程遵循 BSD Socket API,这套接口非常强大且被广泛支持。
可以将 Socket 想象成一个端点(Endpoint),它代表了网络通信的一端。就像电话通信需要一个电话号码和一部电话机一样,网络通信也需要一个地址(IP + 端口)和一个用于收发数据的“接口”,这个接口就是 Socket。
send
, recv
, connect
, listen
等)。read
, write
或专用的 send
, recv
)都通过这个文件描述符进行,这体现了 Linux “一切皆文件”的哲学。一个 Socket 由以下几个关键属性定义:
AF_INET
: IPv4 协议族。AF_INET6
: IPv6 协议族。AF_UNIX
/ AF_LOCAL
: 本地进程间通信(Unix Domain Socket)。AF_INET
。SOCK_STREAM
: 面向连接的、可靠的、基于字节流的服务。通常使用 TCP 协议。数据按顺序到达,无重复。SOCK_DGRAM
: 无连接的、不可靠的、基于数据报的服务。通常使用 UDP 协议。数据以独立的数据包发送,可能丢失、重复或乱序。SOCK_RAW
: 原始套接字,允许直接访问底层网络协议(如 IP、ICMP),用于开发网络工具(如 ping, traceroute)。SOCK_STREAM
对应 TCP,SOCK_DGRAM
对应 UDP)。IPPROTO_TCP
, IPPROTO_UDP
。这是最常见和最可靠的通信模式。
socket
):
c深色版本int sockfd = socket(AF_INET, SOCK_STREAM, 0); // 创建一个用于监听的套接字
sockfd
。bind
):
c深色版本struct sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; // 监听所有网卡 server_addr.sin_port = htons(PORT); // 绑定端口号 bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
listen
):
c深色版本listen(sockfd, BACKLOG);
CLOSED
变为 LISTEN
,开始等待客户端的连接请求。BACKLOG
参数指定了等待连接队列的最大长度。accept
):
c深色版本struct sockaddr_in client_addr; socklen_t client_len = sizeof(client_addr); int client_fd = accept(sockfd, (struct sockaddr*)&client_addr, &client_len);
client_fd
,专门用于与这个特定的客户端通信。sockfd
继续用于监听新的连接。read
/write
或 recv
/send
):
c深色版本char buffer[1024]; int n = read(client_fd, buffer, sizeof(buffer)); // 从客户端读取数据 write(client_fd, "Hello Client!", 13); // 向客户端发送数据close
):
c深色版本close(client_fd); // 关闭与特定客户端的连接 close(sockfd); // 关闭监听套接字(程序结束时)socket
):
c深色版本int sockfd = socket(AF_INET, SOCK_STREAM, 0);connect
):
c深色版本struct sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = inet_addr("服务器IP"); server_addr.sin_port = htons(PORT); connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
read
/write
):
c深色版本write(sockfd, "Hello Server!", 13); // 发送数据到服务器 char buffer[1024]; int n = read(sockfd, buffer, sizeof(buffer)); // 从服务器接收数据close
):
c深色版本close(sockfd);UDP 是无连接的,因此流程更简单,但需要自己处理可靠性。
bind
):
c深色版本bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));ONLINE.SDDANTUOJI.CN24丨JRS.XLSY.CN80丨MAP.HZBESTSEO.COM32丨ZHIBO.JS-SJL.CN68
WEIBO.SDDANTUOJI.CN88丨WEIBO.CSWDYS.COM68丨VIP.JXLGDL.COM16丨M.ZYZJZD.CN72
ZHIBO8.ZYZJZD.CN92丨CCTV.ZYZJZD.CN63丨VIP.NMFZTD.ORG.CN87丨FOOTBALL.PORTASTYL.COM52
FREE.ZYZJZD.CN62丨WEIBO.HZBESTSEO.COM90丨24K.SDDANTUOJI.CN95丨SINA.NMFZTD.ORG.CN81
XLSY.CN88丨24K.CZCJJC.CN93丨24K.HZBESTSEO.COM34丨ZHIBO8.NMFZTD.ORG.CN91
FOOTBALL.JS-SJL.CN80丨ZUQIU.NMFZTD.ORG.CN68丨ZB.SDDANTUOJI.CN18丨ZUQIU.JS-SJL.CN49
PRETTY.HZBESTSEO.COM70丨MOBI.PORTASTYL.COM93丨ZHIBO.JXLGDL.COM44丨SHARE.JXLGDL.COM82
VIP.XLSY.CN93丨QQ.NMFZTD.ORG.CN53丨SHARE.XLSY.CN80丨MOBI.CSWDYS.COM49
LIVE.PORTASTYL.COM86丨ZUQIU.XLSY.CN42丨JRS.CZCJJC.CN54丨BOLL.SDDANTUOJI.CN93
ONLINE.ZYZJZD.CN41丨WWW.JS-SJL.CN54丨BOLL.CZCJJC.CN38丨JRS.JXLGDL.COM43
M.HZBESTSEO.COM46丨TV.PORTASTYL.COM16丨ZB.JXLGDL.COM22丨24K.CSWDYS.COM53
recvfrom
):
c深色版本struct sockaddr_in client_addr; socklen_t client_len = sizeof(client_addr); char buffer[1024]; int n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&client_addr, &client_len);
recvfrom
会返回发送方的地址信息(IP 和端口),这对于后续回复至关重要。sendto
):
c深色版本sendto(sockfd, "Hello UDP Client!", 17, 0, (struct sockaddr*)&client_addr, client_len);
sendto
指定目标地址。close
):
c深色版本close(sockfd);sendto
):
c深色版本sendto(sockfd, "Hello UDP Server!", 17, 0, (struct sockaddr*)&server_addr, sizeof(server_addr));
bind
,系统会自动分配一个临时端口。recvfrom
):
c深色版本char buffer[1024]; int n = recvfrom(sockfd, buffer, sizeof(buffer), 0, NULL, NULL); // 通常不关心服务器的地址,或者已经知道close
):
c深色版本close(sockfd);htons()
(host to network short), htonl()
(host to network long), ntohs()
, ntohl()
进行转换,特别是端口号和 IP 地址。inet_addr()
: 将点分十进制字符串(如 "192.168.1.1")转换为网络字节序的整数。inet_ntoa()
: 反向转换。inet_pton()
和 inet_ntop()
,支持 IPv4 和 IPv6。accept
, read
会等待)。fcntl()
设置为非阻塞模式,配合 select
, poll
, epoll
实现高并发(I/O 多路复用)。perror()
或 strerror(errno)
打印错误信息。shutdown()
可以单独关闭读或写方向。close()
会释放文件描述符并尝试关闭连接。Socket 是 Linux 网络编程的核心。理解其工作原理和编程流程是开发网络应用的基础。
掌握 Socket 编程,你就能构建从简单的客户端/服务器应用到复杂的网络服务。建议从编写一个简单的 TCP 回显服务器/客户端开始实践。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。