代码详细注释:(linux)TCP客户端接收服务器端发的信息

发布于:2025-08-05 ⋅ 阅读:(13) ⋅ 点赞:(0)

服务器端代码

/*2 - TC服务器 */
#include <stdio.h>      // 标准输入输出库
#include <stdlib.h>     // 标准库函数
#include <unistd.h>     // Unix标准函数
#include <sys/socket.h> // 套接字相关函数
#include <sys/types.h>  // 系统数据类型
#include <fcntl.h>      // 文件控制
#include <sys/stat.h>   // 文件状态
#include <netinet/in.h> // 网络地址结构
#include <arpa/inet.h>  // IP地址转换函数

int main(int argc,char *argv[])
{
    if(argc!=3){  // 检查参数数量是否正确
        printf("Usage:%s ip port\n",argv[0]);  // 打印使用方法
        exit(0);  // 退出程序
    }

    //1.创建socket
    int sockfd = socket(AF_INET,SOCK_STREAM,0);  // 创建IPv4 TCP套接字
    if(sockfd==-1){  // 检查socket创建是否成功
        perror("socket");  // 打印错误信息
        exit(-1);  // 异常退出
    }

    //2.绑定ip和端口号(自己)
    struct sockaddr_in addr;  // 定义IPv4地址结构
    addr.sin_family = AF_INET;  // 设置地址族为IPv4
    addr.sin_port = htons(atoi(argv[2]));  // 将端口号转换为网络字节序
    addr.sin_addr.s_addr = inet_addr(argv[1]);  // 将IP地址字符串转换为网络字节序
    int res = bind(sockfd,(struct sockaddr *)&addr,sizeof(addr));  // 绑定套接字到指定地址
    if(res==-1){  // 检查绑定是否成功
        perror("bind");  // 打印错误信息
        exit(-1);  // 异常退出
    }

    //3.监听
    listen(sockfd,10);  // 开始监听,设置最大连接队列为10

    //4.等待客户端连接
    while(1){  // 无限循环,持续接受客户端连接
        struct sockaddr_in cilent_addr;  // 存储客户端地址信息
        socklen_t len = sizeof(cilent_addr);  // 客户端地址结构长度

        // 接受客户端连接
        int newfd = accept(sockfd,(struct sockaddr *)&cilent_addr,&len);
        if(newfd==-1){  // 检查连接是否成功
            perror("accept");  // 打印错误信息
            exit(-1);  // 异常退出
        }
        // 打印客户端IP地址
        printf("%s到此一游!\n",inet_ntoa(cilent_addr.sin_addr));

        //5.和客户端通信
        write(newfd,"hello",6);  // 向客户端发送"hello"消息
        
        //不再通信关闭
        close(newfd);  // 关闭与客户端的连接
    }

    close(sockfd);  // 关闭服务器套接字(实际上永远不会执行到这里)
    return 0;
}

主要流程说明:

  1. 参数检查:检查程序启动参数是否正确(需要IP和端口两个参数)

  2. 创建套接字:创建一个IPv4的TCP套接字

  3. 绑定地址:将套接字绑定到指定的IP地址和端口

  4. 开始监听:设置套接字为监听状态,准备接受客户端连接

  5. 接受连接:循环等待并接受客户端连接

  6. 处理连接:对于每个连接,打印客户端IP并发送"hello"消息

  7. 关闭连接:完成通信后关闭与客户端的连接

注意事项:

  • 服务器会一直运行,直到被手动终止

  • 每次只处理一个客户端连接,发送完消息后立即关闭连接

  • 实际应用中可能需要更复杂的错误处理和并发处理机制

 


 

客户端代码

#include <stdio.h>      // 标准输入输出函数
#include <stdlib.h>     // 标准库函数(如exit)
#include <unistd.h>     // Unix标准函数(如read, write, close)
#include <string.h>     // 字符串处理函数
#include <sys/socket.h> // 套接字相关函数和结构
#include <netinet/in.h> // 互联网地址族定义
#include <arpa/inet.h>  // IP地址转换函数

// 定义常量
#define SERVER_IP "192.168.53.1"  // 服务器IP地址
#define SERVER_PORT 5555          // 服务器端口号
#define BUFFER_SIZE 1024          // 接收缓冲区大小

int main() {
    // 1. 创建socket
    // AF_INET: IPv4协议, SOCK_STREAM: 流式套接字(TCP), 0: 默认协议
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {  // 检查socket是否创建成功
        perror("socket creation failed");  // 打印错误信息
        exit(EXIT_FAILURE);  // 退出程序并返回失败状态
    }

    // 2. 准备服务器地址结构
    struct sockaddr_in server_addr;  // 定义IPv4地址结构
    memset(&server_addr, 0, sizeof(server_addr));  // 清空结构体
    server_addr.sin_family = AF_INET;  // 设置地址族为IPv4
    server_addr.sin_port = htons(SERVER_PORT);  // 设置端口号(转换为网络字节序)
    // 将点分十进制IP转换为网络字节序的二进制形式
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);

    // 3. 连接到服务器
    // 参数:套接字描述符,服务器地址结构,结构体大小
    if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr))) {
        perror("connection failed");  // 连接失败时打印错误
        close(sockfd);  // 关闭套接字
        exit(EXIT_FAILURE);  // 退出程序
    }

    // 连接成功提示
    printf("Connected to server %s:%d\n", SERVER_IP, SERVER_PORT);

    // 4. 接收服务器消息
    char buffer[BUFFER_SIZE];  // 定义接收缓冲区
    // 从套接字读取数据,最大读取BUFFER_SIZE-1字节(保留位置给\0)
    ssize_t bytes_received = read(sockfd, buffer, BUFFER_SIZE - 1);
    if (bytes_received == -1) {  // 读取失败
        perror("read failed");
    } else if (bytes_received == 0) {  // 对端关闭连接
        printf("Server closed the connection\n");
    } else {  // 成功读取数据
        buffer[bytes_received] = '\0'; // 确保字符串以\0结尾
        printf("Received from server: %s\n", buffer);  // 打印接收到的消息
    }

    // 5. 关闭连接
    close(sockfd);  // 关闭套接字
    return 0;  // 正常退出程序
}

关键点详细说明:

  1. socket创建

    • AF_INET 表示使用IPv4协议

    • SOCK_STREAM 表示使用面向连接的TCP协议

    • 第三个参数0表示使用默认协议

  2. 地址结构准备

    • memset 清空结构体是良好的编程习惯

    • htons 将主机字节序的端口号转换为网络字节序

    • inet_addr 将点分十进制的IP字符串转换为网络字节序的二进制形式

  3. 连接过程

    • connect 是阻塞调用,会等待直到连接建立或失败

    • 连接失败时需要先关闭已创建的套接字再退出

  4. 数据接收

    • read 返回读取的字节数,-1表示错误,0表示连接关闭

    • 手动添加字符串终止符\0是安全的做法

  5. 资源清理

    • 程序退出前必须关闭套接字描述符

    • 这是良好的资源管理习惯

这个客户端实现了最基本的TCP连接功能,可以扩展添加发送数据、循环通信等功能。

 


网站公告

今日签到

点亮在社区的每一天
去签到