How to read and write tar file in C?

2019-08-27 15:14发布

I want to read the tar file and write it to another tar file using C. The procedure what I m following here is :

  1. Creating a tar file of the folder
  2. Writing client socket program for reading that tar file as binary file in C using fread function
  3. Writing whatever comes in buffer to socket
  4. Writing server socket program to receive sent data into a buffer
  5. Writing the received buffer into the another tar file.
  6. Closing files and socket.

Here is code :

Server.c

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

#define MAX 1024
#define SOCK_PATH "/tmp/foo"

int s, s2, t, len;
struct sockaddr_un local, remote;

void createSSocket()
{
    if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) 
    {
        perror("socket");
        exit(1);
    }
    printf("\nServer Socket Created...");
}

void setSSocketPath()
{
    local.sun_family = AF_UNIX;
    strcpy(local.sun_path, SOCK_PATH);
    unlink(local.sun_path);
    len = strlen(local.sun_path) + sizeof(local.sun_family);
    printf("\nServer Socket Path Set...");
}

void bindSocket()
{
    if (bind(s, (struct sockaddr *)&local, len) == -1) 
    {
        perror("bind");
        exit(1);
    }
    printf("\nSocket Binded...");
}

void listenSocket()
{   
    if (listen(s, 5) == -1) 
    {
        perror("listen");
        exit(1);
    }
    printf("\nListening Socket...");
}

void acceptConnection()
{
    printf("\nWaiting for a connection...");
    t = sizeof(remote);
    if ((s2 = accept(s, (struct sockaddr *)&remote, &t)) == -1) 
    {
        perror("accept");
        exit(1);
    }
    printf("\nServer Socket Connected...");
}

void closeSSocket()
{
    close(s);
    close(s2);
    printf("\nServer Socket Closed...");
}


void receiveTar()
{
    int len,ret;
    char buf[MAX] = {0};
    char path[MAX] = "/home/priyanka/Codes/3455.tgz";
    FILE* fp;
    fp = fopen(path,"wb");

    while((len = recv(s2,buf,MAX,0)) > 0)
    {
        buf[len] = 0;
        printf("\nReceived : %d",len);
        //fputs(buf,fp);
        //printf("%s",buf);
        ret = fwrite(buf,1,strlen(buf),fp);
        if(ret == -1)
        {
            perror("Error writing to file");
        }
        printf("    Write : %d",ret);
    }
    fclose(fp);
}

int main()
{
    createSSocket();    
    setSSocketPath();
    bindSocket();
    listenSocket();
    acceptConnection(); 

    receiveTar();

    closeSSocket();
    return 0;   
}

Output of Server Program :

Server Socket Created...
Server Socket Path Set...
Socket Binded...
Listening Socket...
Waiting for a connection...
Server Socket Connected...
Received : 1024 Write : 1024
Received : 459 Write : 459
Received : 239 Write : 239
Received : 529 Write : 529
Received : 425 Write : 425
Received : 411 Write : 411
Received : 493 Write : 493
Received : 142 Write : 142
Received : 1024 Write : 1024
Received : 397 Write : 397
Received : 41 Write : 41
Received : 158 Write : 158
Received : 1024 Write : 1024
Received : 705 Write : 705
Received : 505 Write : 505
Received : 1024 Write : 1024
Received : 87 Write : 87
Received : 1024 Write : 1024
Received : 326 Write : 326
Received : 234 Write : 234
Received : 311 Write : 311
Received : 819 Write : 819
Received : 571 Write : 571
Received : 1024 Write : 1024
Received : 1024 Write : 1024
Received : 341 Write : 341
Received : 243 Write : 243
Received : 630 Write : 630
Received : 50 Write : 50
Received : 35 Write : 35
Received : 215 Write : 215
Server Socket Closed...

Client.c

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

#define MAX 1024
#define SOCK_PATH "/tmp/foo"


int s, t, len;
struct sockaddr_un remote;

void createCSocket()
{
    if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) 
    {
        perror("socket");
        exit(1);
    }
    printf("\nClient Socket Created...");
}

void setCSocketPath()
{
    remote.sun_family = AF_UNIX;
    strcpy(remote.sun_path, SOCK_PATH);
    len = strlen(remote.sun_path) + sizeof(remote.sun_family);
    printf("\nClient Socket Path Set...");
}

void connectSocket()
{
    printf("\nTrying to connect...");
    if (connect(s, (struct sockaddr *)&remote, len) == -1) 
    {
        perror("connect");
        exit(1);
    }
    printf("\nClient Connected...\n");
}

void closeCSocket()
{
    close(s);
    printf("\nClient Socket Closed...");
}

void sendTar()
{
    FILE *fp;
    int ret,len;
    char buf[MAX] = {0};
    fp = fopen("/home/priyanka/3455.tgz","rb");
    while(len = fread(buf,1,1024,fp))
    //while((buf[0] = fgetc(fp)) != EOF)
    {
        printf("\nRead : %d",len);
        ret = send(s,buf,strlen(buf),0);
        printf("    Sent : %d",ret);
        if(ret == -1)
        {
            perror("Error sending data : Client");
        }
    }
    fclose(fp);
}

int main()
{
    createCSocket();
    setCSocketPath();
    connectSocket();

    sendTar();

    closeCSocket(); 
    return 0;
}

Output of Client Program :

Client Socket Created...
Client Socket Path Set...
Trying to connect...
Client Connected...

Read : 1024 Sent : 3
Read : 1024 Sent : 1027
Read : 1024 Sent : 273
Read : 1024 Sent : 180
Read : 1024 Sent : 239
Read : 1024 Sent : 529
Read : 1024 Sent : 425
Read : 1024 Sent : 411
Read : 1024 Sent : 493
Read : 1024 Sent : 142
Read : 1024 Sent : 1027
Read : 1024 Sent : 394
Read : 1024 Sent : 41
Read : 1024 Sent : 158
Read : 1024 Sent : 702
Read : 1024 Sent : 1027
Read : 1024 Sent : 503
Read : 1024 Sent : 2
Read : 1024 Sent : 1027
Read : 1024 Sent : 84
Read : 1024 Sent : 1027
Read : 1024 Sent : 323
Read : 1024 Sent : 234
Read : 1024 Sent : 311
Read : 1024 Sent : 819
Read : 1024 Sent : 571
Read : 1024 Sent : 1027
Read : 1024 Sent : 1027
Read : 1024 Sent : 335
Read : 1024 Sent : 243
Read : 1024 Sent : 630
Read : 1024 Sent : 50
Read : 1024 Sent : 35
Read : 315 Sent : 215
Client Socket Closed...

I m facing problems like :

  1. Whatever I m reading in client program only few bytes of it are actually sent and still the receive function is reading MAX number of bytes. Whereas I want my program to read 1024 bytes, sent 1024 bytes, receive 1024 bytes and write 1024 bytes, which is not happening in this case. Will sending length of buffer help to sort out the problem??

  2. Is it the way I m using the right one to send tar file over socket or are there different ways of doing it??

  3. How to check if the data is successfully read, sent, received and written??

2条回答
孤傲高冷的网名
2楼-- · 2019-08-27 15:37

You are reading a binary file with fread and sending chunks as if they were strings:

        ret = send(s,buf,strlen(buf),0);

Use this instead to send just len bytes.

        ret = send(s,buf,len,0);

Similarly, the server program should just write the len bytes received. Appending a '\0' may cause a buffer overflow and writing strlen(buf) bytes will fail to write all the bytes received if a NUL byte is received, as will certainly be the case if a tar file is transmitted:

Change the logic to:

    ret = fwrite(buf,1,len,fp);

You may also want to use the netcat utility: man nc

查看更多
对你真心纯属浪费
3楼-- · 2019-08-27 15:55

There are several versions of libtar, a library to read and write tar archive files in C. You should use it.

If using a network thru tcp(7) sockets(7) (e.g. on Linux or POSIX), remember that TCP/IP is just a stream of bytes without any notion of message: a send(2) (or write) operation on the emitting side does not necessarily correspond to a single recv(2) (or read) operation on the recieving side, the "packets" might have been fragmented or reassembled (e.g. by intermediate routers or by your network hardware or controller or kernel layer). So you always should buffer and manage the byte count of partial read,send,write,recv operations.

查看更多
登录 后发表回答