如何用C实现分布式系统中Server打印TCP/IP信息供Client连接?
C语言实现Server/Client并获取Server自身TCP/IP信息
Server端实现
以下是Server端代码,完成socket创建、绑定、监听,并打印自身的TCP/IP信息:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define PORT 0 // 传0让系统随机分配端口,也可指定固定端口(如8080) #define BACKLOG 5 int main() { int server_fd, new_socket; struct sockaddr_in server_addr, client_addr; socklen_t addr_len = sizeof(server_addr); char server_ip[INET_ADDRSTRLEN]; uint16_t server_port; // 创建TCP socket if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // 设置端口重用,避免程序重启后端口占用问题 int opt = 1; if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { perror("setsockopt"); exit(EXIT_FAILURE); } // 初始化服务器地址结构体 memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; // 监听所有网卡的请求 server_addr.sin_port = htons(PORT); // 绑定socket到指定地址和端口 if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } // 获取Server自身绑定的IP和端口 if (getsockname(server_fd, (struct sockaddr *)&server_addr, &addr_len) < 0) { perror("getsockname failed"); exit(EXIT_FAILURE); } // 把二进制IP转成字符串格式,把网络字节序端口转成本地字节序 inet_ntop(AF_INET, &server_addr.sin_addr, server_ip, INET_ADDRSTRLEN); server_port = ntohs(server_addr.sin_port); // 打印Server信息 printf("Server is listening on:\n"); printf("IP Address: %s (提示:INADDR_ANY代表监听所有网卡,Client连接请填Server真实IP,如192.168.x.x)\n", server_ip); printf("Port: %d\n", server_port); // 开始监听客户端连接 if (listen(server_fd, BACKLOG) < 0) { perror("listen"); exit(EXIT_FAILURE); } printf("Waiting for client connection...\n"); // 接受客户端连接 if ((new_socket = accept(server_fd, (struct sockaddr *)&client_addr, &addr_len)) < 0) { perror("accept"); exit(EXIT_FAILURE); } // 打印连接的Client信息 char client_ip[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, INET_ADDRSTRLEN); printf("Client connected from: %s:%d\n", client_ip, ntohs(client_addr.sin_port)); // 简单消息交互示例 const char *msg = "Hello from Server!"; send(new_socket, msg, strlen(msg), 0); printf("Message sent to client\n"); close(new_socket); close(server_fd); return 0; }
Client端实现
Client端代码支持手动输入Server的IP和端口,完成连接并接收Server消息:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int main() { int sock = 0; struct sockaddr_in serv_addr; char buffer[1024] = {0}; char server_ip[INET_ADDRSTRLEN]; int server_port; // 手动输入Server的IP和端口 printf("Enter Server IP Address: "); scanf("%s", server_ip); printf("Enter Server Port: "); scanf("%d", &server_port); // 创建TCP socket if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket creation failed"); exit(EXIT_FAILURE); } // 初始化Server地址结构体 memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(server_port); // 把字符串IP转成二进制格式 if (inet_pton(AF_INET, server_ip, &serv_addr.sin_addr) <= 0) { perror("invalid address/ address not supported"); exit(EXIT_FAILURE); } // 连接Server if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { perror("connection failed"); exit(EXIT_FAILURE); } // 接收Server发送的消息 read(sock, buffer, 1024); printf("Received from Server: %s\n", buffer); close(sock); return 0; }
关键细节说明
- 获取Server自身信息:核心是
getsockname()函数,必须在bind()操作完成后调用,它能获取当前socket绑定的本地IP和端口。 - IP格式转换:
inet_ntop()将二进制IP转成人类可读的字符串;inet_pton()则把用户输入的字符串IP转成socket可识别的二进制格式。 - 端口字节序处理:网络通信要求使用大端序,本地系统可能是小端序,因此用
htons()将本地端口转为网络字节序,ntohs()将网络端口转成本地字节序用于打印。 - INADDR_ANY说明:如果Server绑定
INADDR_ANY,打印的IP会是0.0.0.0,代表监听所有网卡的请求。此时Client需要填写Server的真实IP(如局域网IP192.168.xxx.xxx),不能用0.0.0.0连接。
编译运行方式
- 编译Server:
gcc server.c -o server - 运行Server:
./server,控制台会打印Server的端口和IP提示 - 编译Client:
gcc client.c -o client - 运行Client:
./client,输入Server的真实IP和打印的端口,即可建立连接
内容的提问来源于stack exchange,提问作者Simple Life
相关产品推荐
相关产品推荐

