признак функции recv () для получения буфера while в одну строку [windows C] - PullRequest
0 голосов
/ 21 января 2010

Этот код отлично отправляет и получает текстовый файл, но не может сделать это в других форматах, таких как .exe или .img. Пожалуйста, помогите мне с этим, так как мне нужно использовать htonl или htons ?? Взгляни !!

Вот функция recv на стороне сервера ::

 if (socket_type != SOCK_DGRAM)
        {

                fi = fopen (final,"wb");
                retval = recv(msgsock, recv_buf, strlen(recv_buf), 0);
                /*recv_buf[retval] = '\0';
                fprintf (fi,"%s",recv_buf);*/

                int i;
                i=atoi(recv_buf);
                char *q;
                q=(char *)malloc(i*sizeof(char));
                retval = recv(msgsock, q, strlen(q), 0);
                //printf ("%s",q);
                fwrite(q,i,1,fi);
                fclose(fi);

        }
        else
        {
            retval = recvfrom(msgsock,recv_buf, sizeof(recv_buf), 0, (struct sockaddr *)&from, &fromlen);
            printf("Server: Received datagram from %s\n", inet_ntoa(from.sin_addr));
            printf ("SOCK_DGRAM");
        }

        if (retval == SOCKET_ERROR)
        {
            fprintf(stderr,"Server: recv() failed: error %d\n", WSAGetLastError());
            closesocket(msgsock);
            //continue;
        }
        else
            printf("Server: recv() is OK.\n");

        if (retval == 0)
        {
            printf("Server: Client closed connection.\n");
            closesocket(msgsock);
                //continue;
        }
        printf("Server: Received %d bytes, data from client\n", retval);

The client side sending function :::

void send_command()
{
    int bytesent;
    FILE *file_out;
    //file_out = fopen(file_path,"rb");
    char str_all[100000];//flag [30]="end";

    ///////////////////////getsize//////////////
    char fsize[5];
    int filesize;
    file_out = fopen(file_path, "rb");
    fseek(file_out, 0, SEEK_END);
    filesize = ftell(file_out);
    rewind (file_out);
    itoa (filesize,fsize,10);
    /////////////////////////////////////////////
    send (ConnectSocket, fsize, strlen (fsize), 0);

    char *r = (char *)malloc (filesize * sizeof(char));

    fread(r,filesize,1,file_out);
    bytesent = send( ConnectSocket, r, strlen(r), 0 );
    printf("\nClient: Bytes sent: %ld\n", bytesent);
    fclose (file_out);

    /*while (fscanf(file_out,"%s",&str_all) != EOF)
    {
        bytesent = send( ConnectSocket, str_all, strlen(str_all), 0 );
        printf("\nClient: Bytes sent: %ld\n", bytesent);
        //Sleep(500);
    }*/

    /*printf("%s",flag);
    send( ConnectSocket, flag, strlen(flag), 0 );*/
    WSACleanup();
    //return 0;
    }

Ответы [ 2 ]

2 голосов
/ 21 января 2010

ОК, в вашей программе несколько проблем.

  • Вы передаете двоичные данные. Получатель увидит только последовательность байтов. Для получателя нет возможности узнать конец данных, поскольку все возможные значения char являются допустимыми значениями данных. Если бы вы отправляли текстовые данные, вы могли бы сказать, что 0 означает конец данных, но теперь вы не можете. Таким образом, вам нужно выбрать «протокол» между сервером и клиентом - самое простое - сервер отправляет длину данных в первых 4 байтах (прочитайте ntonl() и ntohl(), чтобы узнать, как это сделать. это переносимо). Затем получатель будет точно знать, сколько байтов нужно прочитать.
  • Вы объявляете приемный буфер как char *recv_buf, и аналогично для recv_buf1. Вы не выделяете память для любого из двух указателей, поэтому они не указывают ни на что полезное. Тогда ваш recv вызов: recv(msgsock, recv_buf, sizeof(recv_buf), 0); Это также имеет проблемы. Первое упомянутое выше: у вас нет хранилища для recv_buf. Во-вторых, после того, как вы do выделите хранилище для recv_buf, вы берете размер указателя на символ вместо длины буфера, на который указывает recv. Одним из простых способов решения обеих проблем было бы объявить recv_buf как: char recv_buf[SIZE];, а затем использовать sizeof recv_buf в вызове recv().

Я не посмотрел остальную часть вашего кода. Возможно, вам нужно хорошее введение в C и сетевое программирование.

1 голос
/ 21 января 2010

Я думаю, что вы путаете нулевое завершение строки C с концом пакета, отправляемого в сокет. Здесь нет «завершения» пакета, это просто строка байтов. Нули полностью законны, и вы передаете (и получаете) длину явно. Вам, конечно, не нужно использовать внеполосные средства для получения нескольких пакетов. Можете ли вы быть более конкретным о том, что вы спрашиваете?

...