通过C中的套接字发送大文件 [英] Sending large files over socket in c

查看:61
本文介绍了通过C中的套接字发送大文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,此代码适用于最大20KB的小文件,但当我尝试发送或接收大文件时,它有时会停止读取.客户端和服务器的两个功能,用于发送和接收文件.我知道它可能会有一些泄漏和问题,但我稍后会修复.首先,我希望它能正常工作.BUF_SIZE = 512

So this code works ok for small files of up to 20KB but when i try to send or receive larger files it stops reading at some point. Two functions for client and server, to send and receive files. I know it might have some leaks and stuff but I will fix that later. At first I want it to work properly. BUF_SIZE=512

// SENDING BYTES
void send_bytes(int connfd, int client_number, char **command_parts)
{
    FILE *fp;
    fp = fopen(command_parts[1], "r");
    int i = 0;
    // FINDING BYTE SIZE OF THE FILE
    fseek(fp, 0, SEEK_END); /* PUTTING FILE POINTER TO THE END OF THE FILE */
    int num_of_bytes = ftell(fp);
    fseek(fp, 0, SEEK_SET); /* RESETTING FILE POINTER TO THE BEGINNING OF THE FILE */
    char *sendbuff = malloc(num_of_bytes * sizeof(char));
    memset(sendbuff, '\0', num_of_bytes);
    // SENDING TOTAL BYTES TO SEND
    while (write(connfd, itoa(num_of_bytes), 10) < 0)
    {
    }
    printf("\nClient #%d --> Size of file sent: %d\n", client_number, num_of_bytes);

    // IF BYTES MORE THAN 512 SENDING IT IN PARTS
    if(num_of_bytes > BUF_SIZE)
    {
        int bytes_left_to_send = num_of_bytes;
        char *tempbuff = calloc(BUF_SIZE, sizeof(char));
        while(bytes_left_to_send > 0)
        {
            if(bytes_left_to_send >= BUF_SIZE)
            {
                // READING 512 BYTES AND PASSING IT TO TEMPBUFF
                for (i = 0; i < BUF_SIZE; i++)
                {
                    fread(&tempbuff[i], 1, 1, fp);
                }
                // SENDING BYTES
                while (write(connfd, tempbuff, BUF_SIZE) < 0)
                {
                }
                bytes_left_to_send = bytes_left_to_send - BUF_SIZE;
                memset(tempbuff, '\0', BUF_SIZE);
            }
            else
            {
                // READING 512 BYTES AND PASSING IT TO TEMPBUFF
                for (i = 0; i < bytes_left_to_send; i++)
                {
                    fread(&tempbuff[i], 1, 1, fp);
                }
                // SENDING BYTES
                while (write(connfd, tempbuff, bytes_left_to_send) < 0)
                {
                }
                bytes_left_to_send = bytes_left_to_send - bytes_left_to_send;
                memset(tempbuff, '\0', BUF_SIZE);
            }
        }
    }
    else
    {
        // READING EACH BYTE AND PASSING IT TO SENDBUFF
        for (i = 0; i < num_of_bytes; i++)
        {
            fread(&sendbuff[i], 1, 1, fp);
        }
        // SENDING BYTES
        while (write(connfd, sendbuff, num_of_bytes) < 0)
        {
        }
    }

    // FREEING MEMORY
    fclose(fp);
    free(sendbuff);
    printf("\nClient #%d --> File sent\n", client_number);
}
// RECEIVING BYTES
void recv_bytes(int connfd, int client_number, char **command_parts)
{
    int bytes_read = 0, bytes_read_in_total = 0, i = 0;
    char *num_of_bytes = malloc(10 * sizeof(char));
    char *recvbuff = NULL;
    FILE *fp;
    fp = fopen(command_parts[2], "w");
    // RECEIVING BYTES TO RECEIVE
    while (read(connfd, num_of_bytes, 10) < 0)
    {
    }
    printf("\nClient #%d --> Size of file received: %d\n", client_number, atoi(num_of_bytes));
    recvbuff = malloc(atoi(num_of_bytes) * sizeof(char)); /* ALLOCATING recvbuff WITH RECEIVED SIZE */
    memset(recvbuff, '\0', atoi(num_of_bytes));

    // IF BYTES MORE THAN 512 RECEIVING IT IN PARTS
    if(atoi(num_of_bytes) > BUF_SIZE)
    {
        int bytes_left_to_read = atoi(num_of_bytes);
        char *tempbuff = calloc(BUF_SIZE, sizeof(char));
        while(bytes_left_to_read > 0)
        {
            if(bytes_left_to_read >= BUF_SIZE)
            {
                // READING BYTES
                while (bytes_read = read(connfd, tempbuff, BUF_SIZE) < 0)
                {
                }
                bytes_read = strlen(tempbuff);
                // WRITING BYTES READ SO FAR TO THE FILE
                for (i = 0; i < bytes_read; i++)
                {
                    fwrite(&tempbuff[i], 1, 1, fp);
                }
                bytes_left_to_read = bytes_left_to_read - bytes_read;
                memset(tempbuff, '\0', BUF_SIZE);
            }
            else
            {
                // READING BYTES
                while (bytes_read = read(connfd, tempbuff, bytes_left_to_read) < 0)
                {
                }
                bytes_read = strlen(tempbuff);
                // WRITING BYTES READ SO FAR TO THE FILE
                for (i = 0; i < bytes_read; i++)
                {
                    fwrite(&tempbuff[i], 1, 1, fp);
                }
                bytes_left_to_read = bytes_left_to_read - bytes_read;
                memset(tempbuff, '\0', BUF_SIZE);
            }
        }
    }
    else
    {
        // RECEIVING BYTES
        while (bytes_read_in_total < atoi(num_of_bytes))
        {
            while (bytes_read = read(connfd, recvbuff, atoi(num_of_bytes)) < 0)
            {
            }
            bytes_read = strlen(recvbuff);
            bytes_read_in_total = bytes_read_in_total + bytes_read;

            // WRITING BYTES READ SO FAR TO THE FILE
            for (i = 0; i < bytes_read; i++)
            {
                fwrite(&recvbuff[i], 1, 1, fp);
            }
            memset(recvbuff, '\0', atoi(num_of_bytes));
        }
    }

    free(recvbuff);
    fclose(fp);
    printf("\nClient #%d --> File received\n", client_number);
}

推荐答案

我之前已经做过,我需要花一些时间才能给出答案.首先,您必须知道,调用send()时Linux内核不会发出整个缓冲区.其次,在知道文件大小之后,所需的部分是将其分块发送到接收端.我做了512个字节,您可以将其增加到您喜欢的任何大小.接收端也应分块接收,直到接收到所有字节为止.

I have done this before, It would take length for me to give you the answer. First you have to know that the Linux kernel will not send out the whole buffer when you invoke send(). Secondly the part that is required after you know the file size is to then send it in chunks to the receiving end. I did 512 bytes, you could increase it to whatever you like. The receiving end should also receive in chunks until all of the bytes are received.

int sendall(int s, void *buf, int *len)
 {
int total = 0; // how many bytes we've sent
int bytesleft = *len; // how many we have left to send
int n;
while (total < *len) {
    n = send(s, buf+total, bytesleft, 0);
    if (n == -1) {
        break;
    }
    total += n;
    bytesleft -= n;
}
*len = total; // return number actually sent here
return n==-1?-1:0; // return -1 on failure, 0 on success
}

用这个来接收整个缓冲区

Use this one to receive a whole buffer

int recvall(int s, void * buf,int *len)
{
// the workbuffer for storing currently received buffer
char workbuffer[*len];
// Holds the number of received bytes */
int total = 0;
// Holds the number of sent bytes
int n;
//holds the number of bytes left to received
int bytesleft = *len;
while (total < *len)
{
    // recv and append to workbuffer
    n = recv(s,workbuffer+total,bytesleft,0);
    if (n== -1 || n == 0) {
        break;
    }

    // increment total by the number of received bytes
    total += n;
    bytesleft -= n;
}
// Copy workbuffer to to buf
memcpy(buf,workbuffer,sizeof(workbuffer));
switch(n)
{
  case -1:
return -1;
  break;
  case 0:
return 0;
  break;
  default:
return total;
}

您可以下载我编写的小程序,quad(Qucik上传和下载).基本上,它应该演示如何传输大文件.这是 https://www.dropbox.com/s/xpqhflgx6ps89vq/quad.zip?dl=0

You can download the small program I wrote, quad (Qucik Upload and Download). Basically it should demonstrate how large files are transferred. Here's the https://www.dropbox.com/s/xpqhflgx6ps89vq/quad.zip?dl=0

wget https://www.dropbox.com/s/xpqhflgx6ps89vq/quad.zip?dl=0 -O quad.zip
unzip quad.zip
cd quad/src
make clean
sudo apt-get install libncurses-dev
make
#uploading: ./quad -v -u -i /home/me/myfile.txt -a 0.0.0.0 -p 4444
#downloading:  ./quad -v -d -l 4444 -o /home/me/Downloads

这篇关于通过C中的套接字发送大文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆