You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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连接。

编译运行方式

  1. 编译Server:gcc server.c -o server
  2. 运行Server:./server,控制台会打印Server的端口和IP提示
  3. 编译Client:gcc client.c -o client
  4. 运行Client:./client,输入Server的真实IP和打印的端口,即可建立连接

内容的提问来源于stack exchange,提问作者Simple Life

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 15:33:24