网络通信两台机器

一、跨机器通信核心原理

1. 通信要素

2. 数据流向示意

客户端机器(IP_A) → 网络路由 → 服务端机器(IP_B)
   ↓ 发送请求(IP_B:PORT)           ↑ 返回响应

二、实现步骤(以 TCP 为例)

1. 服务端(远程机器)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>

#define PORT 8080 // 需确保该端口在防火墙开放

int main() {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int addrlen = sizeof(address);
    char buffer[1024] = {0};

    // 创建Socket
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }

    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY; // 绑定所有网络接口
    address.sin_port = htons(PORT);

    // 绑定端口
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

    // 监听
    if (listen(server_fd, 3) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    printf("Server listening on 0.0.0.0:%d...\n", PORT);

    // 接受连接
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address, 
                           (socklen_t*)&addrlen)) < 0) {
        perror("accept");
        exit(EXIT_FAILURE);
    }

    // 获取客户端IP
    char client_ip[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, &address.sin_addr, client_ip, INET_ADDRSTRLEN);
    printf("Connection from %s\n", client_ip);

    // 接收数据
    read(new_socket, buffer, 1024);
    printf("Client: %s\n", buffer);

    // 发送响应
    char *response = "Message received by server";
    send(new_socket, response, strlen(response), 0);

    close(new_socket);
    close(server_fd);
    return 0;
}

2. 客户端(本地机器)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

#define SERVER_IP "192.168.1.100" // 替换为服务端实际公网IP
#define PORT 8080

int main() {
    int sock = 0;
    struct sockaddr_in serv_addr;

    // 创建Socket
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket creation error");
        return -1;
    }

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);

    // 转换服务端IP地址
    if (inet_pton(AF_INET, SERVER_IP, &serv_addr.sin_addr) <= 0) {
        perror("Invalid address");
        return -1;
    }

    // 连接服务端
    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
        perror("Connection Failed");
        return -1;
    }

    // 发送数据
    char *message = "Hello from client machine";
    send(sock, message, strlen(message), 0);
    printf("Message sent\n");

    // 接收响应
    char buffer[1024] = {0};
    read(sock, buffer, 1024);
    printf("Server response: %s\n", buffer);

    close(sock);
    return 0;
}

三、关键配置要点

1. 网络环境准备

2. 测试网络连通性

# 客户端测试能否访问服务端端口
telnet 服务器IP 8080       # Linux/macOS
Test-NetConnection 服务器IP -Port 8080 # Windows PowerShell

# 服务端查看监听状态
netstat -tuln | grep 8080  # Linux/macOS
netstat -ano | findstr 8080 # Windows

四、跨机器通信的特殊处理

1. 字节序转换

// 发送整型数据示例(客户端)
uint32_t num = 123456;
uint32_t net_num = htonl(num); // 主机序转网络序
send(sock, &net_num, sizeof(net_num), 0);

// 接收端处理(服务端)
uint32_t net_num;
recv(sock, &net_num, sizeof(net_num), 0);
uint32_t host_num = ntohl(net_num); // 网络序转主机序

2. 超时处理

// 设置连接超时(客户端)
struct timeval timeout;
timeout.tv_sec = 5;  // 5秒超时
timeout.tv_usec = 0;

setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));

3. 处理多网卡场景

// 服务端绑定特定IP(如192.168.1.100)
address.sin_addr.s_addr = inet_addr("192.168.1.100"); // 替换为实际内网IP

五、典型问题排查表

六、进阶实现:跨平台兼容方案

// 条件编译处理不同系统差异
#ifdef _WIN32
    #include <winsock2.h>
    #pragma comment(lib, "ws2_32.lib")
    #define close closesocket
#else
    #include <sys/socket.h>
    #include <arpa/inet.h>
#endif

// 初始化Windows Socket环境
void init_network() {
    #ifdef _WIN32
        WSADATA wsa;
        WSAStartup(MAKEWORD(2,2), &wsa);
    #endif
}

// 清理资源
void cleanup_network() {
    #ifdef _WIN32
        WSACleanup();
    #endif
}

七、实战测试流程

1、服务端部署

  • 云服务器(如 AWS EC2)运行服务端程序

  • 开放安全组的入站端口(如TCP 8080)

2、客户端连接

# 编译客户端
gcc client.c -o client

# 运行(替换实际IP)
./client 54.238.112.36 8080

3、抓包验证

# 在服务端用tcpdump抓包
sudo tcpdump -i eth0 port 8080 -nn -vv

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值