C ++, функция Send () отправляет дополнительные байты - PullRequest
2 голосов
/ 10 сентября 2011

У меня проблемы с классами-оболочками Winsock2 (клиент-сервер), и после бесчисленных часов бессмысленной путаницы я решил, что было бы лучше, если бы я спросил ваше мнение.

Если говорить точнее, проблема в том, что каждый раз, когда я использую функцию Send (), и клиент, и сервер (не всегда!) Отправляют один или два дополнительных байта!

Например, я использую SendBytes («Hello»), а функция Recv возвращает «Hello •» с «•» или другими случайными символами в конце массива символов.

    //main.cpp (Client)
    #include "Socket.h"

    int main() 
    {
        NetworkService::Client cService = NetworkService::Client();
        int res = cService.Initialize("127.0.0.1","20248");
        if(res == 0){
            int local = cService.SendBytes("Hello!");
            printf("Bytes Sent: %ld\n", local);
            cService.Shutdown();

            char* temp = cService.Recv();
            printf("String Recieved: %s  - Size: %d",temp,strlen(temp));
            printf("\nSTRLEN: %d",strlen("X5"));
        }
        else{
            cService.Clean();
        }
        cService.Close();
        while(!kbhit());
        return 0;
    }

Конечно, сервер отправляет строку "X5", а клиент печатает стрельцы ...

//The result with "X5" as the dummy text:  
String Recieved: X5? - Size: 3 //Notice the extra '?' character  
STRLEN: 2

Отправить // Получить функции

    int NetworkService::Client::SendBytes(char* lData){
            int local = send( ConnectSocket, lData, (int)strlen(lData), 0 );
            if (local == SOCKET_ERROR) {
                Close();
                return WSAGetLastError();
            }
            return local;
    }

    char* NetworkService::Client::Recv(){
        recv(ConnectSocket, recvbuf , recvbuflen, 0);
        return recvbuf;
    }

Помощь будет оценена ^ _ ^.

Ответы [ 3 ]

3 голосов
/ 10 сентября 2011

Простите, но

 int local;
 (...)
 return (int*)local;

Чего вы пытались достичь? В вашем коде много серьезных проблем.

2 голосов
/ 10 сентября 2011

Это не способ отправки данных по сети. Слишком много ошибок.

Если вы хотите отправить по сети строки с нулевым символом в конце:

int local = send( ConnectSocket, lData, (int)strlen(lData), 0 );

как все говорили, вы на самом деле не отправляете нулевой терминатор. Вы бы отправили его, если бы добавили 1 к длине. Более того, с длинными строками функция send() не гарантирует, что вы отправите всю строку сразу. Вы должны проверить это и повторно отправить недостающую часть.

recv(ConnectSocket, recvbuf , recvbuflen, 0);

Вы не проверяете возвращаемое значение, поэтому не можете знать длину полученной строки. Поскольку вы не отправляете нулевой байт, полученные данные не заканчиваются нулем. Кроме того, если нулевой терминатор является единственным разделителем большего количества данных, которые вы отправляете, вам придется читать побайтно (не эффективно), чтобы не пропустить нулевой терминатор, чтобы знать, когда заканчивать. Альтернативой может быть создание собственной схемы буферизации (чтобы при следующем чтении частично возвращался результат предыдущего), или изменение протокола, чтобы заранее была известна длина передаваемых данных. Также здесь применимо то же замечание о частичном чтении, что и с функцией send.

Кстати, возвращение статического / глобального буфера не является признаком хорошего кода.

1 голос
/ 10 сентября 2011

Вы не действительно проверяете возвращаемое значение recv.

Есть время, но оно ничего не делает. Вы возвращаетесь из функции без надлежащей обработки ошибок, даже когда recv не удается, но вы никогда не узнаете об этом.

Также вы не отправляете завершающий \0, что не обязательно плохо, зависит от того, что вы пытаетесь сделать, например, вы можете добавить это после получения.

...