如何用NBTExplorer轻松管理你的Minecraft游戏数据
2026/7/2 13:59:34
OSI(开放系统互连)模型是描述网络通信的通用框架,将网络功能划分为 7 层,每层各司其职:
| 层级 | 核心功能 |
|---|---|
| 应用层 | 为用户提供网络服务(邮件、文件传输、网页访问等) |
| 表示层 | 统一数据表示形式(编码、加密、格式转换) |
| 会话层 | 管理进程间会话(建立、维护、终止通信连接) |
| 传输层 | 管理端到端数据传输(提供可靠 / 不可靠传输服务) |
| 网络层 | 负责路由选择与网际互连(IP 地址寻址、跨网络数据转发) |
| 数据链路层 | 相邻主机间数据传输(MAC 地址寻址、数据帧封装、差错控制,含 LLC/MAC 子层) |
| 物理层 | 把数据转为电信号传输(定义机械、电气特性,如双绞线、光纤、无线信道) |
OSI 是理论模型,而 TCP/IP 是互联网的实际协议体系,它将 OSI 七层合并为四层(也有五层划分),是我们实际开发中接触的核心:
| TCP/IP 层级 | 对应 OSI 层级 | 核心协议 |
|---|---|---|
| 应用层 | 应用层 + 表示层 + 会话层 | HTTP(网页)、FTP/TFTP(文件传输)、DNS(域名解析)、SNMP(网络管理)、DHCP(动态 IP 分配) |
| 传输层 | 传输层 | TCP(可靠传输,如文件传输)、UDP(无连接,低延迟,如音视频) |
| 网络层 | 网络层 | IP(主机寻址)、ICMP(ping 测试)、RIP/OSPF(路由协议)、IGMP(组播) |
| 接口层 | 数据链路层 + 物理层 | ARP(IP 转 MAC)、RARP(MAC 转 IP) |
192.168.0.112:50000)。htons/ntohs函数转换端口,inet_addr转换 IP)。/etc/network/interfaces,修改后执行sudo /etc/init.d/networking restart生效。ifconfig ens33 192.168.0.13/24 up(重启后失效)。ifconfig:查看本机网络配置(IP、网卡信息)。ping www.baidu.com:测试网络连通性。netstat -anp:查看本机所有网络连接(进程、端口、协议)。Socket 是「打开网络设备后获得的文件描述符」,是网络编程的入口 —— 通过 Socket,我们可以像操作文件一样进行网络数据的收发。
UDP(用户数据报协议)是无连接、低延迟的传输层协议,适合音视频、实时通信等场景,核心特性:
| 服务端(提供服务) | 客户端(使用服务) |
|---|---|
socket()→ 创建套接字 | socket()→ 创建套接字 |
bind()→ 绑定 IP + 端口 | 无需绑定(系统自动分配端口) |
recvfrom()→ 接收客户端数据 | sendto()→ 发送数据到服务端 |
sendto()→ (可选)回显数据 | recvfrom()→ (可选)接收响应 |
close()→ 关闭套接字 | close()→ 关闭套接字 |
c
运行
int socket(int domain, int type, int protocol);domain:地址族(AF_INET= 互联网协议,AF_UNIX= 单机通信);type:套接字类型(SOCK_DGRAM=UDP,SOCK_STREAM=TCP);protocol:协议(0 = 自动适配);c
运行
int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);sockfd:套接字描述符;my_addr:地址结构体(IPv4 用struct sockaddr_in);addrlen:地址结构体长度;IPv4 地址结构体:
c
运行
struct sockaddr_in { u_short sin_family; // 地址族(AF_INET) u_short sin_port; // 端口(网络字节序) struct in_addr sin_addr; // IP地址(网络字节序) };c
运行
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);buf:待发送数据缓冲区;len:发送数据长度;flags:0 = 阻塞发送;dest_addr:目标主机地址结构体;c
运行
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);buf:接收数据缓冲区;len:缓冲区大小;src_addr:(可选)发送方地址结构体(NULL 表示不关心);c
运行
#include <arpa/inet.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <unistd.h> #include <fcntl.h> typedef struct sockaddr* SA; #define SAVE_FILE "/home/linux/received.png" int main() { int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (-1 == sockfd) { perror("socket"); return 1; } struct sockaddr_in ser, cli; bzero(&ser, sizeof(ser)); ser.sin_family = AF_INET; ser.sin_port = htons(50000); ser.sin_addr.s_addr = inet_addr("192.168.0.112"); if (-1 == bind(sockfd, (SA)&ser, sizeof(ser))) { perror("bind"); close(sockfd); return 1; } int fp = open(SAVE_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (-1 == fp) { perror("open"); close(sockfd); return 1; } socklen_t len = sizeof(cli); printf("UDP服务端启动,端口50000等待接收...\n"); while (1) { char buf[512] = {0}; ssize_t recv_len = recvfrom(sockfd, buf, sizeof(buf), 0, (SA)&cli, &len); if (recv_len <= 0) { perror("recvfrom"); break; } printf("接收客户端(%s:%d)数据:%ld字节\n", inet_ntoa(cli.sin_addr), ntohs(cli.sin_port), recv_len); write(fp, buf, recv_len); const char *resp = "OK"; sendto(sockfd, resp, strlen(resp)+1, 0, (SA)&cli, len); bzero(buf, sizeof(buf)); } close(fp); close(sockfd); return 0; }c
运行
#include <arpa/inet.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <unistd.h> #include <fcntl.h> typedef struct sockaddr* SA; int main() { int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (-1 == sockfd) { perror("socket"); return 1; } struct sockaddr_in ser; bzero(&ser, sizeof(ser)); ser.sin_family = AF_INET; ser.sin_port = htons(50000); ser.sin_addr.s_addr = inet_addr("192.168.0.112"); int fp = open("/home/linux/1.png", O_RDONLY); if (-1 == fp) { perror("open"); close(sockfd); return 1; } char buf[512] = {0}; while (1) { int ret = read(fp, buf, sizeof(buf)-1); if (ret <= 0) break; sendto(sockfd, buf, ret, 0, (SA)&ser, sizeof(ser)); bzero(buf, sizeof(buf)); int recv_len = recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL); if (recv_len > 0) printf("服务端响应:%s\n", buf); bzero(buf, sizeof(buf)); } close(fp); close(sockfd); return 0; }