簡體   English   中英

通過C中的套接字發送大文件

[英]Sending large files over socket in c

因此,此代碼適用於最大20KB的小文件,但是當我嘗試發送或接收大文件時,它有時會停止讀取。 客戶端和服務器的兩個功能,用於發送和接收文件。 我知道它可能會有一些泄漏和問題,但我稍后會修復。 首先,我希望它能正常工作。 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個字節,您可以將其增加到任意大小。 接收端也應分塊接收,直到接收到所有字節為止。

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
}

用這個來接收整個緩沖區

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

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM