简体   繁体   English

套接字程序 - 使用 UDP 的可靠数据传输

[英]socket program - reliable data transfer using UDP

I have written code for reliable data transfer in C. Here the client sends the file to the server in chunks of 1024 bytes.我已经用 C 编写了可靠数据传输的代码。在这里,客户端将文件以 1024 字节的块发送到服务器。 And the server writes the packets received into another file.服务器将接收到的数据包写入另一个文件。

The program works fine for string file/binary data file.该程序适用于字符串文件/二进制数据文件。 But when I try to copy image file there comes the problem.但是当我尝试复制图像文件时出现了问题。 when I try transferring .jpg file there is no compilation error or run time error.当我尝试传输 .jpg 文件时,没有编译错误或运行时错误。 But when I try opening the destination file it says, "could not open image file','error interpreting jpeg file' ' improper call to jpeg library in state 201".但是,当我尝试打开目标文件时,它说“无法打开图像文件”,“解释 jpeg 文件时出错”,“在状态 201 中对 jpeg 库的调用不当”。

Can anybody look into the codes and suggest any solution?任何人都可以查看代码并提出任何解决方案吗?

Here is my client code这是我的客户端代码

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

char *itoa(long i,char *s,int dummy_radix)
{
    sprintf(s,"%ld",i);
    return s;
}

int main(int argc, int *argv[])
{
    int sock,length,n;
    struct sockaddr_in server,from;
    struct hostent *hp;
    long int packets =0;
    unsigned char buff[1024] = {0};

    // checking if hostname and the port address is provided //
    if(argc!=3)
    {
        printf("insufficient arguments\n");
        exit(1);
    }

    //create a socket//
    sock = socket(AF_INET,SOCK_DGRAM,0);

    if(sock<0)
    {
        printf("error in opening socket\n");
        return 1;
    }

    //to get  the hostname of the system or the machine//
    hp= gethostbyname(argv[1]);

    if(hp==0)
    {
        printf("Unknown host\n");
        return 1;
    }
    //build the server's IP address //
    bzero((char *)&server,sizeof(server));
    bcopy((char*)hp->h_addr,(char *)&server.sin_addr,hp->h_length);
    server.sin_family = AF_INET;
    server.sin_port =  htons(atoi(argv[2]));
    length = sizeof(server);

    /*open the file that we wish to transfer*/
    FILE *fp = fopen("landscape.jpeg","rb");
    if(fp==NULL)
    {
        printf("file open error");
        return 1;
    }
    fseek(fp,0,SEEK_END); //if exists read the size of the file 
    size_t file_size = ftell(fp);
    fseek(fp,0,SEEK_SET); 

    printf("size of the file is %d\n", file_size);

    /*find the number of packets*/
    packets = (file_size/1024)+1 ;

    /*send the number of packets to the server*/
    itoa(packets,buff,10);
    n = sendto(sock,buff,strlen(buff),0,(struct sockaddr *)&server,sizeof(struct sockaddr));
    if(n<0)
    {
        printf("error in sending message to the serveR");
        return 1;
    }

    /*Read data from file and send it*/
    int packetNum = 0;
    while(1)
    {
        /*First read file in chunks of  1024  bytes */
        int nread = fread(buff,1,1024,fp);
        //printf("Bytes read %d\n",nread);

        /*if read was success ,send data*/
        if(nread>0)
        {
            //printf("data sent now is %s\n",buff);
            n = sendto(sock,buff,strlen(buff),0,(struct sockaddr *)&server,sizeof(struct sockaddr));
            printf("Sending %d, numBytes sent: %d\n", packetNum, n);
            packetNum++;
            if(n<0)
            {
                printf("error in sending message to the server");
                fclose(fp);
                return 1;
            }
        }

        /*There is something tricky going on with the read..
         * Either there was error ,or we reached end of  file.
         */
        if(nread<1024)
        {
            if(feof(fp))
                printf("End of file\n");

            if(ferror(fp))
                printf("Error reading\n");
            break;
        }
    }
    close(sock);
    fclose(fp);

    return 0;
}

Here is my server code这是我的服务器代码

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

int main(int argc, char *argv[])
{
    int sock,length,fromlen,n;
    struct sockaddr_in server;
    struct sockaddr_in from;
    char buf[1024];
    char file_buf[1024];
    int packets = 0;
    int received = 0;
    FILE *newfp;
    newfp = fopen("output.jpeg","wb");
    if(newfp==NULL)
    {
        printf("error opening the file\n");
        return 1;
    }    
    if(argc<2)
    {
        fprintf(stderr, "no port number specified\n");
        exit(0);
    }
    sock = socket(AF_INET,SOCK_DGRAM,0);
    if(sock<0)
    {
        printf("error in opening socket\n");
        return 1;
    }
    length = sizeof(server);
    bzero(&server,length);
    server.sin_family= AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons(atoi(argv[1]));
    if(bind(sock,(struct sockaddr*)&server,length)<0)
    {
        printf("cannot bind\n");
        return 1;
    }
    fromlen = sizeof(struct sockaddr_in);
    n = recvfrom(sock,buf,1024,0,(struct sockaddr *)&from,&fromlen);
    if(n<0)
    {
        printf("recvfrom  error\n");
        return 1;
    }

    packets = atoi(buf);
    printf("Num packets expected: %d\n", packets);

    while(received<packets)
    {
        n = recvfrom(sock,buf,sizeof (buf),0,(struct sockaddr *)&from,&fromlen);    

        //printf ("%d\n", n);
        printf("Packet num %d, numBytes received: %d\n", received, n);

        if(n<0)
        {
            printf("recvfrom  error\n");
            return 1;
        }
        //printf("%s",buf);
        if((fwrite(buf,1,n,newfp)) < n)
        {
            printf("error in writing to the file\n");
            return 1;
        }
        received++;
    }
    printf("Finished\n");
    fclose(newfp);
    return 0;
}
  1. You are assuming that fread() null-terminates the buffer.您假设fread()空值终止缓冲区。 It doesn't.它没有。
  2. You are assuming that the data doesn't contain other nulls: it can.您假设数据不包含其他空值:它可以。
  3. You should use nread instead of strlen(buffer) as the count parameter when sending the file data.发送文件数据时,您应该使用nread而不是strlen(buffer)作为计数参数。
  4. The correct test for end of file is not nread < 1024 , which can happen any time: it is nread == 0 .文件结尾的正确测试不是nread < 1024 ,这可能随时发生:它是nread == 0
  5. You aren't handling out of sequence packets, or missing or duplicated ones.您不会处理乱序的数据包,或者丢失或重复的数据包。 In fact there is nothing reliable about this code at all.事实上,这段代码根本不可靠。 You need sequence numbers in the packets, which are removed when writing the data to the file;您需要数据包中的序列号,在将数据写入文件时将其删除; you need an ACK or NACK mechanism for missing packets;你需要一个 ACK​​ 或 NACK 机制来丢失数据包; you need a mechanism that ignores duplicates;您需要一种忽略重复项的机制; ... ...

You've barely started.你才刚刚开始。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM