2011-01-30 3 views
1

Я хочу отправить строку «Hello there», но я получаю «re». Почему это?Проблема с C++ recv()

void Accept() 
{ 
    SOCKADDR_IN sock; 
    int intsock = sizeof(sock); 
    remoteSocket = ::accept(desc, (LPSOCKADDR)&sock, &intsock); 
    if(remoteSocket == -1) 
    { 
     cout << "Error in Accept()" << endl; 
    } 
    HandleConnection(); 
} 

void HandleConnection() 
{ 
    cout << "You are connected !!!" << endl; 
    char* temp = new char[20]; 
    Recv(temp); 
    cout << temp << endl; 
} 

void Send(const char* buffer) 
{ 
    if((::send(remoteSocket, buffer, strlen(buffer), 0)) < 0) 
    { 
     cout << "Error in Send()" << endl; 
    } 
} 

void Recv(char* buffer) 
{ 
    int n = 0; 
    while((n = ::recv(remoteSocket, buffer, strlen(buffer), 0)) 0) 
    { 
     buffer[n] = 0; 
    } 
} 

~Server() 
{ 
    WSACleanup(); 
} 

}; 

int main() 
{ 
    Server s; 
    s.Initialize(); 
    s.Socket(); 
    s.Bind(); 
    s.Listen(); 
    while(1) 
    { 
     s.Accept(); 
    } 
    return 0; 
} 
+0

Код, который вы отправили, не компилируется. Например, у вас есть деструктор ('~ Server') вне определения класса. –

+0

strlen идет в бесконечном цикле, если вы забыли * escape * строку с \ 0 на конце. Кроме того, вы пробовали использовать select()? Используя это, вы можете подождать, пока не получите некоторые данные. В сокете TCP recv() будет возвращать столько, сколько может быть предоставленный буфер –

+0

Другая проблема (отличная от Marlon): HandleConnection() использует 'new' без' delete'. Опять же, нет причин, по которым вам нужно «новое» здесь. Вместо этого вы можете использовать переменную стека. –

ответ

5

Несмотря на проблеме деструктора указываемой @Billy ONeal, вы делаете recv() в цикле, но каждый раз, когда вы переписываете полученный буфер. Я считаю, что вы хотите что-то вроде этого:

// Pass buffer and its real size. This function takes care of NULL termination. 
size_t Recv(char* buffer, size_t size) { 
    size_t total = 0, n = 0; 
    while((n = ::recv(remoteSocket, buffer+total, size-total-1, 0)) > 0) { 
     total += n; 
    } 
    buffer[total] = 0; 
    return total; 
} 

int main() { 
    char buffer[128]; 
    // Connect or whatever (and set your global remoteSocket) 
    Recv(buffer, sizeof(buffer)); 
    cout << buffer << endl; 
    return 0; 
} 
+0

не должен быть 'if (total> 0) buffer [total - 1] = 0;'? –

+0

Он переписывает полученный буфер при вызове strlen (buffer) каждый раз в цикле, поэтому каждый вызов strlen (buffer) будет становиться все меньше и меньше, если сообщения становятся меньше и меньше – Marlon

+0

@bstn: Условие имеет смысл, если сокет ** неблокируется **. Функция 'recv' возвращает количество байтов, которые она прочитала. Если он считывает 10 байтов, мы сохраняем 10 байтов в буфер (буфер [0] в буфер [9]) и устанавливаем 10-й байт в 0. Вызывающий отвечает за передачу «buffer size-1» этой функции. – jweyrich

3

Я думаю, что проблема эта строка кода while((n = ::recv(remoteSocket, buffer, strlen(buffer), 0)) 0)

Вы используете strlen(buffer), чтобы получить размер буфера, который является неправильным, вы должны передать sizeof(buffer) вашему Recv функции.

Если это не проблема, то это одна из проблем: P

Edit:

Как отметил Kitsune и Марк, SizeOf (буфер) будет возвращать 4 или 8 байт, так как это выделяется в куче и является просто указателем на блок памяти. Если вы решите использовать стек (char buffer[20] вместо new char[20]), вы можете передать sizeof (буфер) в свою функцию Recv. В противном случае, просто использовать жёстко прописанные 20.

Это то, что ваш код должен выглядеть следующим образом:

void HandleConnection() 
{ 
    cout << "You are connected !!!" << endl; 
    char temp[20]; // <-- now we have an array 
    Recv(temp, sizeof(temp)); // <-- sizeof(temp) will give us 20, not 4 anymore 
    cout << temp << endl; 
} 

Recv(char* buffer, size_t buffer_size) 
{ 
    recv(remoteSocket, buffer, buffer_size, 0); 
} 
+1

sizeof (buffer) - 4 или 8 (32/64b).Вам нужно будет установить известный размер буфера. Либо передайте размер в, локально выделите массив (в tis случае sizeof будет фактический размер), либо используйте какой-либо другой тип (вектор может работать ...) – KitsuneYMG

+0

Я думаю, что sizeof (buffer) в этом контексте просто быть 4 (или 8, если 64-битная архитектура). Размер буфера, вероятно, необходимо будет передать из вызывающего метода. Но +1 для определения проблемы. –

+0

Да, вот как это выглядит сейчас :) спасибо Marlon – Kobe

2

Вы должны указать, как большой буфер, который получает данные есть - это не strlen(buffer).

Вы можете использовать sizeof(buffer), если массив буфера определен локально как массив (не в списке параметров), или если буфер является глобальным массивом или массивом области видимости объекта, определение которого видимо в функции. В противном случае вам нужно использовать дополнительный параметр размера буфера, который вы передаете функции Recv() - то есть, если буфер определен в другой функции или если он динамически распределен. (В коде определение массива не отображается в Recv(), поэтому вам необходимо убедиться, что Recv() знает размер как-то - либо в качестве явного дополнительного аргумента, либо потому, что вы завершаете буфер в соответствующем классе, который включает в себя метод, который сообщает вы, сколько места выделяются в буфер он держит.

конечно, код, как показано, не компилируется, поскольку buffer в действительности не определен или объявлен в любом месте.

+0

буфер его аргумент функции – Kobe

+0

@vBx - как я пропустил это? –

+0

@ Jonathan Leffler: все еще, если я использую sizeof (аргумент), я получаю 4 – Kobe

Смежные вопросы