基于TCP协议的网络客户端和服务端

发布于:2024-05-11 ⋅ 阅读:(152) ⋅ 点赞:(0)

服务端

tcp_server.c

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <unistd.h>  
#include <arpa/inet.h>  
#define BUF_SIZE 1024  // 定义一个宏,用于设置缓冲区大小为1024字节  
  
int main() {  // 主函数入口  
    int iServer, iClient;  // 声明服务器和客户端socket变量  
    struct sockaddr_in stServer, stClient;  // 声明服务器和客户端的地址结构体  
    char buf[BUF_SIZE];  // 声明一个字符数组,用于存储接收到的数据  
  
    // 创建socket  
    iServer = socket(AF_INET, SOCK_STREAM, 0);  // 创建一个IPv4的TCP socket  
    if (iServer == -1) {  // 如果socket创建失败  
        perror("socket error");  // 输出错误信息  
        exit(1);  // 退出程序  
    }  
  
    // 绑定地址和端口  
    memset(&stServer, 0, sizeof(stServer));  // 初始化服务器地址结构体,设置为全0  
    stServer.sin_family = AF_INET;  // 设置地址族为IPv4  
    stServer.sin_addr.s_addr = INADDR_ANY;  // 设置服务器IP地址为任意地址(监听所有网络接口)  
    stServer.sin_port = htons(12345);  // 设置服务器端口为12345,htons函数用于将主机字节序转换为网络字节序  
    if (bind(iServer, (struct sockaddr *)&stServer, sizeof(stServer)) == -1) {  // 绑定socket到地址和端口  
        perror("bind error");  // 如果绑定失败,输出错误信息  
        exit(1);  // 退出程序  
    }  
  
    // 监听连接  
    if (listen(iServer, 5) == -1) {  // 开始监听连接,最大挂起连接数为5  
        perror("listen error");  // 如果监听失败,输出错误信息  
        exit(1);  // 退出程序  
    }  
  
    // 接收客户端连接  
    socklen_t len = sizeof(struct sockaddr_in);  // 声明一个socklen_t变量,用于存储地址结构体的长度  
    iClient = accept(iServer, (struct sockaddr *)&stClient, &len);  // 等待并接受客户端的连接请求  
    if (iClient == -1) {  // 如果接受连接失败  
        perror("accept error");  // 输出错误信息  
        exit(1);  // 退出程序  
    }  
    printf("accept ok! iClient = %d\n", iClient);  // 打印接受的客户端socket的描述符  
  
    // 与客户端进行持续通信  
    while (1) {  // 无限循环,用于持续接收和发送数据  
        memset(buf, 0, BUF_SIZE);  // 清空缓冲区  
        int ret = recv(iClient, buf, BUF_SIZE - 1, 0);  // 从客户端接收数据,注意缓冲区大小减1以留出空间给字符串结束符'\0'  
        if (ret <= 0) {  // 如果接收数据失败或客户端关闭连接  
            if (ret == 0) {  // 如果接收到的数据长度为0,说明客户端正常关闭连接  
                printf("Client closed the connection\n");  // 打印提示信息  
            } else {  // 如果接收失败  
                perror("recv error");  // 输出错误信息  
            }  
            break;  // 跳出循环,结束通信  
        }  
  
        printf("recv data ok! buf = %s\n", buf);  // 打印接收到的数据  
  
        // 回显数据给客户端  
        ret = send(iClient, buf, strlen(buf), 0);  // 将接收到的数据(作为字符串)回显给客户端  
        if (ret <= 0) {  // 如果发送数据失败  
            perror("send error");  // 输出错误信息  
            break;  // 跳出循环,结束通信  
        }  
        printf("send data ok! %s\n", buf);  // 打印发送的数据(注:这里实际上已经打印过了接收的数据,可能只是想表明发送成功)  
    }  
  
    // 关闭客户端连接  
    close(iClient);  // 关闭与客户端的连接  
    printf("Connection with client closed\n");  // 打印连接已关闭的信息  
  
    // 关闭服务器socket(如果需要)  
    close(iServer);  // 关闭服务器socket  
  
    return 0;  // 程序正常结束,返回0  
}

客户端

tcp_client.c

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <unistd.h>  
#include <arpa/inet.h>  
#define BUF_SIZE 1024 // 定义一个宏,用于设置缓冲区大小为1024字节

int main() { // 主函数入口
int iClient; // 声明客户端socket变量
struct sockaddr_in stServer; // 声明服务器地址结构体
char buf[BUF_SIZE]; // 声明一个字符数组,用于存储接收和发送的数据

// 创建socket  
// 创建一个IPv4的TCP socket  
iClient = socket(AF_INET, SOCK_STREAM, 0);    
if (iClient == -1) {  // 如果socket创建失败  
    perror("socket error");  // 输出错误信息  
    exit(1);  // 退出程序  
}  
 
// 设置服务器地址和端口  
// 初始化服务器地址结构体,设置为全0  
memset(&stServer, 0, sizeof(stServer));    
stServer.sin_family = AF_INET;  // 设置地址族为IPv4  
// 假设服务器和客户端在同一台机器上,设置服务器IP地址为127.0.0.1  
stServer.sin_addr.s_addr = inet_addr("127.0.0.1");   
stServer.sin_port = htons(12345);  // 设置服务器端口为12345,htons函数用于将主机字节序转换为网络字节序  
 
// 连接到服务器  
// 尝试连接到服务器  
if (connect(iClient, (struct sockaddr *)&stServer, sizeof(stServer)) == -1) {    
    perror("connect error");  // 如果连接失败,输出错误信息  
    exit(1);  // 退出程序  
}  
printf("connect ok!\n");  // 打印连接成功的消息  
 
// 与服务器进行持续通信  
while (1) {  // 无限循环,用于持续接收和发送数据  
    printf("Enter message to send (or 'quit' to exit): ");  // 提示用户输入要发送的消息或输入'quit'退出  
 
    // 读取用户输入  
    // 从标准输入读取最多BUF_SIZE-1个字符到buf中,并保留一个位置给字符串结束符'\0'  
    fgets(buf, BUF_SIZE - 1, stdin);    
 
    // 移除换行符(如果存在)  
    // 找到换行符并替换为字符串结束符'\0'  
    buf[strcspn(buf, "\n")] = 0;    
 
    // 检查是否输入了'quit'  
    // 如果用户输入的是'quit',则跳出循环  
    if (strcmp(buf, "quit") == 0) {    
        break;    
    }  
 
    // 发送数据到服务器  
    // 将用户输入的数据发送到服务器  
    int ret = send(iClient, buf, strlen(buf), 0);    
    if (ret <= 0) {  // 如果发送数据失败  
        perror("send error");  // 输出错误信息  
        break;  // 跳出循环,结束通信  
    }  
 
    // 接收服务器回显的数据  
    // 清空缓冲区以准备接收新数据  
    memset(buf, 0, BUF_SIZE);    
    // 从服务器接收数据到buf中  
    ret = recv(iClient, buf, BUF_SIZE - 1, 0);    
    if (ret <= 0) {  // 如果接收数据失败或服务器关闭连接  
        if (ret == 0) {  // 如果接收到的数据长度为0,说明服务器正常关闭连接  
            printf("Server closed the connection\n");  // 打印提示信息  
        } else {  // 如果接收失败  
            perror("recv error");  // 输出错误信息  
        }  
        break;  // 跳出循环,结束通信  
    }  
 
    // 打印从服务器接收到的数据  
    printf("Received from server: %s\n", buf);    
}  
 
// 关闭连接  
// 关闭与服务器的连接  
close(iClient);    
printf("Connection with server closed\n");  // 打印连接已关闭的信息  
 
return 0;  // 程序正常结束,返回0
}


网站公告

今日签到

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