c - 如何在C中读写tar文件?

标签 c sockets binaryfiles fwrite fread

我想读取 tar 文件并使用 C 将其写入另一个 tar 文件。我在这里遵循的过程是:

  1. 创建文件夹的 tar 文件
  2. 编写客户端套接字程序,使用 fread 函数在 C 中将 tar 文件读取为二进制文件
  3. 将缓冲区中的任何内容写入套接字
  4. 编写服务器套接字程序将发送的数据接收到缓冲区
  5. 将接收到的缓冲区写入另一个 tar 文件。
  6. 关闭文件和套接字。

代码如下:

服务器.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;   
}

服务器程序的输出:

已创建服务器套接字...
服务器套接字路径设置...
套接字绑定(bind)...
监听套接字...
等待连接...
服务器套接字已连接...
接收:1024 写入:1024
收到:459 写:459
收到:239 写:239
收到:529 写:529
收到:425 写:425
收到:411 写:411
收到:493 写:493
收到:142 写:142
接收:1024 写入:1024
收到:397 写:397
收到:41 写:41
接收:158 写入:158
接收:1024 写入:1024
接收:705 写入:705
接收:505 写入:505
接收:1024 写入:1024
收信:87 写信:87
接收:1024 写入:1024
接收:326 写入:326
收到:234 写:234
接收:311 写入:311
收信:819 写信:819
收到:571 写:571
接收:1024 写入:1024
接收:1024 写入:1024
收到:341 写:341
收到:243 写:243
接收:630 写入:630
收到:50 写:50
收到 : 35 写 : 35
收到:215 写:215
服务器套接字已关闭...

客户端.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;
}

客户端程序的输出:

客户端套接字已创建...
客户端套接字路径设置...
正在尝试连接...
客户端已连接...

读取:1024 发送:3
读取:1024 发送:1027
读取:1024 发送:273
读取:1024 发送:180
读取:1024 发送:239
读取:1024 发送:529
读取:1024 发送:425
读取:1024 发送:411
读取:1024 发送:493
读取:1024 发送:142
读取:1024 发送:1027
读取:1024 发送:394
读取:1024 发送:41
读取:1024 发送:158
读取:1024 发送:702
读取:1024 发送:1027
读取:1024 发送:503
读取:1024 发送:2
读取:1024 发送:1027
读取:1024 发送:84
读取:1024 发送:1027
读取:1024 发送:323
读取:1024 发送:234
读取:1024 发送:311
读取:1024 发送:819
读取:1024 发送:571
读取:1024 发送:1027
读取:1024 发送:1027
读取:1024 发送:335
读取:1024 发送:243
读取:1024 发送:630
读取:1024 发送:50
读取:1024 发送:35
读取:315 发送:215
客户端套接字已关闭...

我正面临这样的问题:

  1. 无论我在客户端程序中读取什么,实际发送的只有几个字节,接收函数仍在读取最大字节数。而我希望我的程序读取 1024 个字节,发送 1024 个字节,接收 1024 个字节并写入 1024 个字节,这在这种情况下不会发生。发送缓冲区长度是否有助于解决问题??

  2. 是我使用正确的方式通过套接字发送 tar 文件还是有不同的方式?

  3. 如何查看数据是否成功读取、发送、接收、写入??

最佳答案

您正在使用 fread 读取二进制文件并像发送字符串一样发送 block :

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

改用它来发送 len 个字节。

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

同样,服务器程序应该只写入接收到的len 个字节。附加一个'\0' 可能会导致缓冲区溢出并且写入strlen(buf) 字节将无法写入接收到的所有字节,如果收到一个NUL 字节,肯定会这样如果传输的是 tar 文件,则会出现这种情况:

将逻辑更改为:

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

您可能还想使用 netcat 实用程序:man nc

关于c - 如何在C中读写tar文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29091786/

相关文章:

c - Fwrite 不会复制二进制文件副本中的所有字节

c - 动态内存分配 - 时间和原因

java - 仅程序打印/接收每个其他数据包

Java Sockets - 接收空白缓冲区

c++ - 二进制模式+格式化文本操作还是文本模式+二进制数据操作——有意义吗?

Python:从二进制数据中解压结构数组的最佳方法是什么

c - 修改 detab 以接受制表位列表

c - 我删除结构条目的代码没有删除,我不明白为什么

c - 避免翘曲发散

java - 当多个请求到来时保持 java 套接字处于 Activity 状态