2011-01-30 96 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`)。 – 2011-01-30 01:14:34

+0

如果忘記* \ escape *字符串結尾的\ 0,strlen會進入無限循環。另外,你有沒有嘗試過使用select()?使用它你可以等待,直到你收到一些數據。在TCP套接字上,recv()將返回與提供的緩衝區一樣多的容量 – 2011-01-30 01:18:28

+0

另一個問題(除了Marlon之外):HandleConnection()使用`new`而不使用`delete`。再說一次,這裏沒有理由需要「新」。您可以改爲使用堆棧變量。 – 2011-01-30 01:19:15

回答

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; 
} 
3

我認爲這個問題是這行代碼while((n = ::recv(remoteSocket, buffer, strlen(buffer), 0)) 0)

您正在使用strlen(buffer)拿到這是不正確,你應該傳遞sizeof(buffer)Recv功能的緩衝區的大小。

如果這不是問題,那麼它是存在的問題之一:P

編輯:

正如所指出的狐狸和Mark,的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); 
} 
2

您需要指定接收數據的緩衝區有多大 - 這是不是strlen(buffer)

如果緩衝區數組在本地定義爲數組(不在參數列表中),或者緩衝區是全局或文件範圍數組,其定義在函數中可見,則可以使用sizeof(buffer)。否則,您需要使用傳遞給Recv()函數的額外緩衝區大小參數 - 也就是說,如果緩衝區是在另一個函數中定義的,或者它是動態分配的。 (在代碼中,數組定義在Recv()中不可見,所以您需要確保Recv()以某種方式知道大小 - 要麼作爲明確的額外參數,要麼將緩衝區包裝在適當的類中,該類包含一個方法,你有多少空間分配給其持有的緩衝區。

當然,如不編譯,因爲buffer代碼實際上沒有定義或任何聲明。