c++ socket TCP/IP发送文件,大文件

以下用C++代码实现了文件的发送与接收

服务器端

#include <iostream>
#include <stdio.h>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
//缓存大小设置不能超过2M
#define BUFF_SIZE (1024 * 1024)
#define FILE_NAME_LENGTH 1024
int s;                     /* socket for accepting connections    */
int ns;                    /* socket connected to client          */

int exitFunc() {
    closesocket(s);
    closesocket(ns);
    return 0;
}

long long int getFileSize(const char* filePath) {
    FILE* f;
    f = fopen(filePath, "rb");
    if (NULL == f) {
        printf("getFileSize fopen error\n");
        return -1;
    }

    if (0 != fseek(f, 0, SEEK_END)) {
        printf("getFileSize fseek error\n");
        return -1;
    }

    long long int fileSize = ftell(f);
    if (fileSize < 0) {
        printf("ftell error\n");
    }
    printf("fileSize:%lld\n", fileSize);
    fclose(f);
    return fileSize;
}

char* getFileName(const char* filePath) {
    bool bFound = false;
    char* buff = new char[1024];
    memset(buff, 0, 1024);
    while (!bFound) {
        int lastIndex = 0;
        for (int i = 0; i < strlen(filePath); ++i) {
            if (filePath[i] == '\\' || filePath[i] == '/') {
                lastIndex = i;
            }
        }
        for (int i = lastIndex + 1; i < strlen(filePath); ++i) {
            buff[i - lastIndex - 1] = filePath[i];
        }
        bFound = true;
    }
    return buff;
}

int main(int argc, char** argv)
{
    _onexit(exitFunc);
    unsigned short port;       /* port server binds to                */
    char buff[BUFF_SIZE];              /* buffer for sending & receiving data */
    struct sockaddr_in client; /* client address information          */
    struct sockaddr_in server; /* server address information          */
    int namelen;               /* length of client name               */
    const char* filePath = new char[FILE_NAME_LENGTH];
    port = 5010;
    filePath = "D:\\PT\\bet.mkv";   //这里自行选择
    long long int fileSize = getFileSize(filePath);
    printf("fileSize:%lld\n", fileSize);
    char* fileName = getFileName(filePath);
    printf("fileName:%s\n", fileName);

    WSADATA wsadata;
    WSAStartup(0x202, &wsadata);

    //创建socket服务
    if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("socket error\n");
        exit(2);
    }

    //socket和服务地址绑定
    server.sin_family = AF_INET;
    server.sin_port = htons(port);
    server.sin_addr.s_addr = INADDR_ANY;

    if (bind(s, (struct sockaddr*)&server, sizeof(server)) < 0)
    {
        printf("bind error\n");
        exit(3);
    }

    //监听服务,只允许一个客户端连接
    if (listen(s, 1) != 0)
    {
        printf("listen error\n");
        exit(4);
    }

    //等待连接
    namelen = sizeof(client);
    while (true) {
        //循环 一直等待客户端的连接
        if ((ns = accept(s, (struct sockaddr*)&client, &namelen)) == -1)
        {
            printf("accept error\n");
            exit(5);
        }

        //有客户端连接过来之后 将指定文件发送给客户端
        FILE* f;
        f = fopen(filePath, "rb");
        if (f == NULL) {
            printf("file:%s doesn't exist\n", filePath);
            exit(6);
        }

        long long int sendSize = 0;
        //先将文件大小的数据发送给客户端
        _ltoa(fileSize, buff, 10);
        if (send(ns, buff, sizeof(buff), 0) < 0) {
            printf("send fileSize to client error\n");
            exit(7);
        }
        //再将文件名发送给客户端
        printf("sizeof:%d strlen:%d\n", sizeof(fileName), strlen(fileName));
        if (send(ns, fileName, strlen(fileName), 0) < 0) {
            printf("send fileName to client error\n");
            exit(7);
        }
        while (sendSize < fileSize) {
            memset(buff, 0, 1024 * 1024);
            size_t iread = fread(buff, sizeof(char), BUFF_SIZE, f);
            printf("iread:%d\n", iread);
            if (iread < 0) {
                printf("fread error\n");
                fclose(f);
                break;
            }
            int iSend = send(ns, buff, iread, 0);
            if (iSend < 0) {
                printf("send error\n");
                fclose(f);
                break;
            }
            sendSize += iSend;
            printf("fileSize:%lld iSend:%d sendSize:%lld\n", fileSize, iSend, sendSize);
            fseek(f, sendSize, SEEK_SET);
        }
        fclose(f);
    }
    printf("Server ended successfully\n");
    exit(0);
}

客户端

#include <iostream>

#include <stdio.h>
#include <WinSock2.h>
#include <time.h>
#include<string>
using namespace std;
#define BUFF_SIZE (1024 * 1024)
#define FILE_NAME_LENGTH 1024
int s;                     /* client socket                       */
int exitFunc() {
    closesocket(s);
    return 0;
}

int main(int argc, char** argv)
{
    _onexit(exitFunc);

    WSADATA wsadata;
    WSAStartup(0x202, &wsadata);
    printf("start...\n");

    unsigned short port;       //服务端口
    char buf[BUFF_SIZE];       //缓存
    struct hostent* hostnm;    //服务地址信息
    struct sockaddr_in server; //服务sockaddr信息

    hostnm = gethostbyname("127.0.0.1");
    if (hostnm == (struct hostent*)0)
    {
        fprintf(stderr, "Gethostbyname failed\n");
        exit(2);
    }

    
    port = 2000;
    server.sin_family = AF_INET;
    server.sin_port = htons(port);
    server.sin_addr.s_addr = *((unsigned long*)hostnm->h_addr);

    //创建socket
    if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("Socket error\n");
        exit(3);
    }

    //准备连接服务端
    printf("ready to connet to server ...\n");
    if (connect(s, (struct sockaddr*)&server, sizeof(server)) < 0)
    {
        printf("Connect error\n");
        exit(4);
    }

    //先接收文件大小
    int iRecv = 0;
    memset(buf, 0, BUFF_SIZE);
    iRecv = recv(s, buf, BUFF_SIZE, 0);
    if (iRecv < 0) {
        printf("recv fileSize error\n");
        exit(5);
    }
    long long int totalFileSize = atoll(buf);
    printf("totalFileSize:%lld\n", totalFileSize);
    //再接收文件名
    memset(buf, 0, BUFF_SIZE);
    iRecv = recv(s, buf, BUFF_SIZE, 0);
    if (iRecv < 0) {
        printf("recv fileName error\n");
        exit(5);
    }
    char fileName[FILE_NAME_LENGTH];
    memset(fileName, 0, FILE_NAME_LENGTH);
    memcpy(fileName, buf, strlen(buf));
    printf("recv fileName:%s\n", fileName);

    //接收文件 将文件保存到指定位置
    char* filePath = new char[FILE_NAME_LENGTH];
    memset(filePath, 0, FILE_NAME_LENGTH);
    const char* basePath = "D:\\client\\";
    memcpy(filePath, basePath, strlen(basePath));
    strcat(filePath, fileName);
    printf("filePath:%s\n", filePath);

    FILE* f = NULL;
    f = fopen(filePath, "wb");
    if (f == NULL) {
        printf("file:%s doesn't exist and failed to create\n", filePath);
        exit(5);
    }

    long long int fileRecv = 0;
    time_t start;
    start = time(NULL);

    while (fileRecv < totalFileSize) {
        memset(buf, 0, BUFF_SIZE);
        iRecv = recv(s, buf, BUFF_SIZE, 0);
        if (iRecv < 0)
        {
            printf("Recv error\n");
            exit(6);
        }
        if (iRecv == 0) {
            break;
        }
        fileRecv += iRecv;
        time_t end = time(NULL);
        time_t cost = end - start;
        //动态计算出传输完需要用时多久
        time_t totalTime = 0;
        //计算出剩余时间
        time_t leftTime = 0;
        if (cost != 0) {
            totalTime = totalFileSize / (fileRecv / cost);
            leftTime = (totalFileSize - fileRecv) / (fileRecv / cost);
        }
        printf("totalFileSize:%lld recv file size:%lld, totalTime:%d 's, leftTime:%d 's\n", totalFileSize, fileRecv, totalTime, leftTime);
        fwrite(buf, sizeof(char), iRecv, f);
    }
    fclose(f);

    printf("Client Ended Successfully\n");
    exit(0);
}

以上代码我是在vs2019里跑成的。先运行服务器端进行监听,然后运行客户端,如果连接成功,那么传输就会开始,文件路径可以自行修改

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Sure, I can help you with that! Here's an example of how to implement TCP/IP socket communication in C: Step 1: Set up the server ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <arpa/inet.h> #define PORT 8080 int main(int argc, char const *argv[]) { int server_fd, new_socket; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); char buffer[1024] = {0}; char *hello = "Hello from server"; // Creating socket file descriptor if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // Forcefully attaching socket to the port 8080 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 ); // Forcefully attaching socket to the port 8080 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); } if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) { perror("accept"); exit(EXIT_FAILURE); } // Send a message to the client send(new_socket, hello, strlen(hello), 0); printf("Hello message sent\n"); // Close the socket close(server_fd); return 0; } ``` Step 2: Set up the client ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #define PORT 8080 int main(int argc, char const *argv[]) { int sock = 0, valread; struct sockaddr_in serv_addr; char *hello = "Hello from client"; char buffer[1024] = {0}; // Creating socket file descriptor 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); // Convert IPv4 and IPv6 addresses from text to binary form 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; } send(sock, hello, strlen(hello), 0); printf("Hello message sent\n"); valread = read(sock, buffer, 1024); printf("%s\n", buffer); return 0; } ``` Note: This code is for educational purposes only and should not be used in production without proper testing and modification. Do test it on local-host. Hope this helps!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值