2011-01-30 57 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代码实际上没有定义或任何声明。