如何在C中读写tar文件?
How to read and write tar file in C?
我想读取 tar 文件并使用 C 将其写入另一个 tar 文件。我在这里遵循的过程是:
- 正在创建文件夹的 tar 文件
- 编写客户端套接字程序以使用 fread 函数在 C 中将 tar 文件读取为二进制文件
- 将缓冲区中的任何内容写入套接字
- 编写服务器套接字程序以将发送的数据接收到缓冲区
- 正在将接收到的缓冲区写入另一个 tar 文件。
- 正在关闭文件和套接字。
这是代码:
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;
}
服务器程序的输出:
已创建服务器套接字...
服务器套接字路径设置...
套接字绑定...
侦听套接字...
正在等待连接...
服务器套接字已连接...
接收: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
服务器套接字已关闭...
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;
}
客户端程序的输出:
已创建客户端套接字...
客户端套接字路径设置...
正在尝试连接...
客户端已连接...
读取: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
客户端套接字已关闭...
我正面临这样的问题:
无论我在客户端程序中读取什么,实际发送的只有几个字节,接收函数仍在读取最大字节数。而我希望我的程序读取 1024 个字节,发送 1024 个字节,接收 1024 个字节并写入 1024 个字节,这在这种情况下不会发生。发送缓冲区长度是否有助于解决问题??
是我使用正确的方法通过套接字发送 tar 文件还是有不同的方法?
如何查看数据读取、发送、接收、写入是否成功??
您正在使用 fread
读取二进制文件并像发送字符串一样发送块:
ret = send(s,buf,strlen(buf),0);
改用此方法仅发送 len
个字节。
ret = send(s,buf,len,0);
同样,服务器程序应该只写入收到的 len
个字节。附加 '[=16=]'
可能会导致缓冲区溢出,如果收到 NUL 字节,写入 strlen(buf)
字节将无法写入收到的所有字节,如果 tar 文件是肯定会出现这种情况转发:
将逻辑更改为:
ret = fwrite(buf,1,len,fp);
您可能还想使用 netcat 实用程序:man nc
有几个版本的 libtar,一个用 C 语言读取和写入 tar
归档文件的库。你应该使用它。
如果在接收方通过 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)(或 read
)操作使用网络,"packets" 可能已被分段或重新组装(例如,通过中间路由器或您的网络硬件或控制器或内核层)。因此,您始终应该缓冲和管理部分 read
、send
、write
、recv
操作的字节数。
我想读取 tar 文件并使用 C 将其写入另一个 tar 文件。我在这里遵循的过程是:
- 正在创建文件夹的 tar 文件
- 编写客户端套接字程序以使用 fread 函数在 C 中将 tar 文件读取为二进制文件
- 将缓冲区中的任何内容写入套接字
- 编写服务器套接字程序以将发送的数据接收到缓冲区
- 正在将接收到的缓冲区写入另一个 tar 文件。
- 正在关闭文件和套接字。
这是代码:
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;
}
服务器程序的输出:
已创建服务器套接字...
服务器套接字路径设置...
套接字绑定...
侦听套接字...
正在等待连接...
服务器套接字已连接...
接收: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
服务器套接字已关闭...
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;
}
客户端程序的输出:
已创建客户端套接字...
客户端套接字路径设置...
正在尝试连接...
客户端已连接...
读取: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
客户端套接字已关闭...
我正面临这样的问题:
无论我在客户端程序中读取什么,实际发送的只有几个字节,接收函数仍在读取最大字节数。而我希望我的程序读取 1024 个字节,发送 1024 个字节,接收 1024 个字节并写入 1024 个字节,这在这种情况下不会发生。发送缓冲区长度是否有助于解决问题??
是我使用正确的方法通过套接字发送 tar 文件还是有不同的方法?
如何查看数据读取、发送、接收、写入是否成功??
您正在使用 fread
读取二进制文件并像发送字符串一样发送块:
ret = send(s,buf,strlen(buf),0);
改用此方法仅发送 len
个字节。
ret = send(s,buf,len,0);
同样,服务器程序应该只写入收到的 len
个字节。附加 '[=16=]'
可能会导致缓冲区溢出,如果收到 NUL 字节,写入 strlen(buf)
字节将无法写入收到的所有字节,如果 tar 文件是肯定会出现这种情况转发:
将逻辑更改为:
ret = fwrite(buf,1,len,fp);
您可能还想使用 netcat 实用程序:man nc
有几个版本的 libtar,一个用 C 语言读取和写入 tar
归档文件的库。你应该使用它。
如果在接收方通过 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)(或 read
)操作使用网络,"packets" 可能已被分段或重新组装(例如,通过中间路由器或您的网络硬件或控制器或内核层)。因此,您始终应该缓冲和管理部分 read
、send
、write
、recv
操作的字节数。