C使用TCP协议进行文件传输

C使用TCP协议进行文件传输TOC

实现方法

1.服务端程序创建一个 TCP 服务器套接字,并且绑定到特定的 IP 地址和端口上,开始监听客户端的连接请求。

2.客户端程序创建一个 TCP 客户端套接字,并且连接到服务器的 IP 地址和端口。

3.客户端向服务端发送待传输的文件名,服务端接收到文件名后,判断文件是否存在,如果存在则回复客户端,并发送文件大小给客户端。

4.客户端接收到服务端回复,并获取到文件大小后,开始发送文件数据。客户端可以通过循环读取文件数据,并且调用 send() 函数将数据发送给服务端。

5.服务端接收到客户端发送的数据后,将数据写入文件中。服务端可以通过循环接收数据,并且调用 write() 函数将数据写入文件。

6.当客户端发送完所有数据后,关闭套接字,并且通知服务端文件传输已经完成。服务端接收到客户端发送的数据后,关闭套接字。

注意

1.在文件传输过程中需要考虑数据的完整性和准确性,可以通过计算校验和或使用哈希算法来校验传输数据的正确性。

2.当传输的文件较大时,需要分批进行传输,可以通过分块传输的方式进行。

3.在传输数据之前,需要将数据进行封装,添加一些元信息,用于传输控制和数据校验。

4.在编写程序时需要考虑网络延迟、丢包等问题,采用合适的方式进行重传或者补偿。

5.在传输文件时需要考虑数据安全性以及传输过程中的加密和解密等问题。

直接上代码

服务端程序:

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

#define PORT 8888

int main()
{
    int server_fd, new_socket, valread;
    struct sockaddr_in address;
    int opt = 1;
    int addrlen = sizeof(address);

    // 创建 TCP 服务器套接字
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
    {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }

    // 设置套接字选项,允许重用地址和端口
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
                   &opt, sizeof(opt)))
    {
        perror("setsockopt");
        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("Waiting for connections...\n");

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

    printf("Connection accepted.\n");

    // 接收客户端发送的文件名
    char filename[1024];
    valread = read(new_socket, filename, 1024);
    if (valread < 0)
    {
        perror("read");
        exit(EXIT_FAILURE);
    }

    printf("Received filename: %s\n", filename);

    // 打开文件并获取文件大小
    FILE *fp;
    if ((fp = fopen(filename, "rb")) == NULL)
    {
        perror("fopen");
        exit(EXIT_FAILURE);
    }
    fseek(fp, 0, SEEK_END);
    int file_size = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    // 回复客户端并发送文件大小
    char filesize_str[32];
    sprintf(filesize_str, "%d", file_size);
    valread = send(new_socket, filesize_str, strlen(filesize_str), 0);
    if (valread < 0)
    {
        perror("send");
        exit(EXIT_FAILURE);
    }

    // 发送文件数据
    char buffer[1024];
    int bytes_read;
    while ((bytes_read = fread(buffer, 1, 1024, fp)) > 0)
    {
        if (send(new_socket, buffer, bytes_read, 0) != bytes_read)
        {
            perror("send");
            exit(EXIT_FAILURE);
        }
    }

    fclose(fp);
    close(new_socket);
    close(server_fd);

    printf("File transfer completed.\n");

    return 0;
}

客户端程序:

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

#define PORT 8888

int main(int argc, char const *argv[])
{
    int sock = 0, valread;
    struct sockaddr_in serv_addr;
    char buffer[1024] = {0};

    // 创建 TCP 客户端套接字
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("\n Socket creation error \n");
        return -1;
    }

    memset(&serv_addr, '0', sizeof(serv_addr));

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

    // 将 IP 地址从点分十进制转换为二进制形式
    if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0)
    {
        printf("\nInvalid address/ Address not supported \n");
        return -1;
    }

    // 连接到服务器
    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    {
        printf("\nConnection Failed \n");
        return -1;
    }

    // 发送文件名
    char *filename = "test.jpg";
    valread = send(sock, filename, strlen(filename), 0);
    if (valread < 0)
    {
        perror("send");
        return -1;
    }

    // 接收文件大小
    char filesize_str[32];
    valread = read(sock, filesize_str, 32);
    if (valread < 0)
    {
        perror("read");
        return -1;
    }
    int file_size = atoi(filesize_str);

    // 接收文件数据
    FILE *fp;
    if ((fp = fopen("recv.jpg", "wb")) == NULL)
    {
        perror("fopen");
        return -1;
    }
    int bytes_received = 0;
    int bytes_left = file_size;
    while (bytes_left > 0)
    {
        int bytes_to_receive = bytes_left < 1024 ? bytes_left : 1024;
        bytes_received = read(sock, buffer, bytes_to_receive);
        if (bytes_received < 0)
        {
            perror("read");
            return -1;
        }
        fwrite(buffer, 1, bytes_received, fp);
        bytes_left -= bytes_received;
    }

    fclose(fp);
    close(sock);

    printf("File transfer completed.\n");

    return 0;
}
  • 4
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
基于TCP协议C语言文件传输可以通过以下步骤完成: 1. 建立TCP Socket 使用socket()函数创建一个TCP套接字,即创建一个用于网络通信的端点。 2. 连接到服务器 使用connect()函数将客户端的套接字连接到服务器的IP地址和端口。 3. 打开要传输文件 使用标准C库函数,如fopen(),打开要传输文件,并将其以二进制形式读取到缓冲区中。 4. 发送文件数据 使用send()函数将文件数据从客户端发送到服务器。可以使用循环读取文件数据并使用send()函数发送,直到文件的所有数据都被发送完毕。 5. 接收文件数据 服务器端使用recv()函数接收来自客户端的文件数据。可以使用循环接收数据并写入到服务器上的文件中,直到接收到完整的文件。 6. 关闭连接和文件文件传输完成后,关闭客户端和服务器端的套接字,并关闭打开的文件。 以上步骤是基于TCP协议进行文件传输的基本流程。但需要注意的是,这只是一个简单的框架,实际的实现可能还需要处理异常情况、错误处理、数据校验以及其他额外的功能。同时,使用TCP协议进行文件传输确保了可靠性,但可能会有一定的性能开销。对于更高性能要求的文件传输,可以考虑使用UDP协议进行传输,但需要自行处理数据的可靠性和丢失问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [基于Linux用C语言实现TCP/UDP图片和文件传输(socket)](https://blog.csdn.net/qq_39768922/article/details/117969620)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值