通过TCP发送的文件使用type:application / octet-stream创建

时间:2013-10-05 16:38:05

标签: c file tcp

我试图使用TCP协议将文件从服务器传输到客户端。 我设法发送文件的整个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 delcarations 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 ?????”哪个???我假设是文件的数据。

问题是创建的“文件”无法打开。帮助?

1 个答案:

答案 0 :(得分:0)

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

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

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

相关问题