gpt4 book ai didi

c - 通过 TCP 发送的文件创建类型为 : application/octet-stream

转载 作者:行者123 更新时间:2023-11-30 17:46:40 24 4
gpt4 key购买 nike

我正在尝试使用 TCP 协议(protocol)将文件从服务器传输到客户端。我设法发送文件的整个syze,但是当客户端创建文件时,它无法打开。在本例中,我发送的是 jpg 文件。

这是 server.c 的代码:

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <arpa/inet.h>
#define PORT 59000

int main(int argc,char *argv[]) {
int port, fd, newfd, n, nw, addrlen;
int port_was_given = 0;
char buffer[128], *ptr, *topic, *data;
size_t result;
struct hostent *h;
struct sockaddr_in addr;
FILE *send;

if((fd=socket(AF_INET,SOCK_STREAM,0))==-1)exit(1); //error
memset((void*)&addr,(int)'\0',sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=htonl(INADDR_ANY);

if (argc == 3) {
port = atoi(argv[2]);
port_was_given = 1;
}

if(port_was_given == 1)
addr.sin_port=htons((u_short)port);
else
addr.sin_port=htons((u_short)PORT);

if(bind(fd,(struct sockaddr*)&addr,sizeof(addr))==-1)exit(1); //error

if(listen(fd,5)==-1)exit(1); //error

while(1) {
addrlen=sizeof(addr);
if((newfd=accept(fd,(struct sockaddr*)&addr,&addrlen))==-1)exit(1); //erro
h=gethostbyaddr((char*)&addr.sin_addr,sizeof(struct in_addr),AF_INET);

while((n=read(newfd,buffer,128))!=0) {
if(n==-1)exit(1);

topic = strtok(buffer," ");
topic = strtok(NULL," ");

if (strcmp(topic, "Nacional\n")==0) {
send = fopen("flag","r");
fseek(send, 0L, SEEK_END); //vai ate ao fim do ficheiro
int sz = ftell(send); //size of file
fseek(send,0L,SEEK_SET);
//rewind(send);
data = (char*)malloc(sizeof(char)*sz);
result = fread(data,1,sz,send);
//fseek(send,0L,SEEK_SET);
fclose(send);
char ptr2[300] = "REP ok ";
char *ptrInt; //for s -> int
sprintf(ptrInt, "%d", sz);
strcat(ptr2, ptrInt);
strcat(ptr2, " ");
strcat(ptr2, data);
strcat(ptr2, "\n");
while(n>0) {
nw=write(newfd,ptr2,n); //write n bytes on each cycle
}

}

}



close(newfd);
}
close(fd);
exit(0);
}

好吧,逻辑是:客户端请求一种内容,在本例中内容是“Nacional”,因此服务器必须将“flag.jpg”发送到客户端。服务器的应答有以下类型:

REP 状态大小数据

状态可以是“ok”或“nok”。如果“nok”,则不会发送文件。size 是数据的大小。data 是文件本身的数据。

现在是client.c:

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <arpa/inet.h>

#define PORT 58000
#define NG 10

int main (int argc,char *argv[])
{

/** ... variables declarations and other stuff ... */

fdtcp=socket(AF_INET,SOCK_STREAM,0);
if (fdtcp==-1) exit(1); // Erro

inet_aton(ip, &address);

if (strcmp(lsname, "localhost")==0)
newHost = gethostbyname("localhost");
else
newHost = gethostbyaddr((const void *)&address,sizeof ip,AF_INET);

newPort = atoi(newport);

memset((void*)&addrtcp,(int)'\0',sizeof(addrtcp));
addrtcp.sin_family=AF_INET;
addrtcp.sin_addr.s_addr=((struct in_addr *)(newHost->h_addr_list[0]))->s_addr;
addrtcp.sin_port=htons((u_short)newPort);

k = connect(fdtcp,(struct sockaddr*)&addrtcp,sizeof(addrtcp));
if (k==-1) exit(1); // Erro

// REQ Tn (Conteudo Solicitado)
ptr = strcat(reqdata, tn);
ptr = strcat(reqdata, "\n");

// Envia-se o Comando REQ
nreqleft = 25;
while(nreqleft>0) {
kwrite=write(fdtcp,ptr,nreqleft);
if (kwrite<=0) exit(1); // Erro
nreqleft -= kwrite;
ptr += kwrite;
}

// Recebe-se o Comando REP
nreqleft = 128;
ptr = &buffertcp[0];
kread=read(fdtcp,ptr,nreqleft);
if (kread==-1) exit(1); // Erro
cmd = strtok(buffertcp, " "); // REP
cmd = strtok(NULL, " "); // Status
if(strcmp(cmd,"ok")) {
printf("ERR\n");
exit(1); // Erro
}
cmd = strtok(NULL, " "); // Size
size = atoi(cmd);
// Recebem-se os Dados do Conteúdo Desejado
nreqleft = size;
char data[size];
ptr = &data[0];
while(nreqleft>0) {
kread=read(fdtcp,ptr,nreqleft);
if (kread==-1) exit(1); // Erro
nreqleft -= kread;
ptr += kread;
}

file = fopen("file","w");
fwrite(data, 1, size, file);
fclose(file);

close(fdtcp);

// --------------------------------------------------- //

exit(0);
}

“其他内容”部分只是变量声明和与另一台服务器的 UDP 连接,与这部分无关,所以我 100% 确定它不会影响这部分。事实上,在 client.c 上,如果我放置从服务器收到的消息的 printf,它将显示“REP ok 31800 ??????”哪个 ???我认为是文件的数据。

问题是创建的"file"无法打开。帮忙?

最佳答案

一个问题是 31800 比 300 大得多,因此当您将 data 附加到服务器中的 ptr2 数组时,就会出现缓冲区溢出。您可以通过在 ptr2 中发送“ header ”后不使用单独的 write() 调用发送数据来纠正此问题。您的 write() 循环看起来会永远循环,但我猜您没有显示所有代码。

在接收器中,我没有看到任何解析 header 以将 header 与数据分开的尝试。由于您最多读取 128 个字节,因此该读取可能已收到文件的 header 和一些数据,并且您不会尝试检测和保存文件的该部分。

在调试文件传输应用程序时,我会从文本文件开始,以便您可以直观地看到生成的文件,并对与实际文件一起保存的文件运行简单的 diff 来查看是否存在是差异。

关于c - 通过 TCP 发送的文件创建类型为 : application/octet-stream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19200108/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com