user2993413 user2993413 - 2 months ago 7
C++ Question

recv() returns always 0

I've a problem with

recv()
function that I can't explain: it always returns 0. I've a client/server application in which the server simply has to receive a string from the client through the internet (different pc).
There are no connectivity problems, and I also tried to send a string from server to client: it worked.
I search in the blog and what I found, recv() socket function returning data with length as 0, non-blocking recv returns 0 when disconnected, Recv returning zero incorrectly, didn't help me to understand.

Here I post the server code:

int main()
{
Network net;
ManagementTask taskManager;

int portNumber = 1500;
net.sockaddr_initialize_server(portNumber);

if (!net.Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))
exit(-1);

if (!net.Bind())
exit(-1);
if (!net.Listen())
exit(-1);

while (1) {
net.setConnectedSocket(SOCKET_ERROR);

while (net.getConnectedSocket() == SOCKET_ERROR) {
cout << "Waiting for connection..." << endl;

if (!net.Accept())
break;
// Create a thread - looking for application state's changes

cout << "Connection established." << endl;
cout << "Waiting for data.." << endl;

net.Recv();

net.Shutdown();
}
}

net.CloseListeningSocket();

net.WSA_Cleanup();

return 0;
}


and the Network class:
Network.h

class Network
{
WSADATA wsaData;
WORD wVersionRequested;
int Port;
unsigned int byteReceived, byteSent;
SOCKET listeningSocket, connectedSocket;
SOCKADDR_IN serverAddr, senderInfo, clientAddr;
int caddrlen;

char buff[DIM];
string buffer;
list <int> commands;

public:
Network();
~Network();
void myFormatMessage(int code);
void setByteReceived(unsigned int byte);
unsigned int getByteReceived();
void setConnectedSocket(SOCKET s);
SOCKET getConnectedSocket();
void setListeningSocket(SOCKET s);
SOCKET getListeningSocket();
void setBuff(char *s);
string getBuffer();
char * getBuff();
void setCommands();
int buffLen();

bool Socket(int family, int type, int protocol);
void sockaddr_initialize_server(const unsigned int port);
bool Bind();
bool Accept();
bool Listen();
void Recv();
void CloseListeningSocket();
void CloseConnectedSocket();
void Shutdown();
void WSA_Cleanup();
};



Network.c

Network::Network()
{
wVersionRequested = MAKEWORD(2, 0);
if (WSAStartup(wVersionRequested, &wsaData) != 0) {
myFormatMessage(WSAGetLastError());
exit(-1);
}
}
Network::~Network()
{
}
void Network::myFormatMessage(int code) {
LPTSTR errcode = 0;
if (code != 0) {
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, code, 0, (LPTSTR)&errcode, 0, NULL);

wcout << code << ": " << errcode << endl;
}
}
// SETTERS AND GETTERS --------------------------------------------------------------
void Network::setByteReceived(unsigned int byte) {
byteReceived = byte;
}
unsigned int Network::getByteReceived() {
return byteReceived;
}
void Network::setConnectedSocket(SOCKET s) {
connectedSocket = s;
}
SOCKET Network::getConnectedSocket() {
return connectedSocket;
}
void Network::setListeningSocket(SOCKET s) {
listeningSocket = s;
}
SOCKET Network::getListeningSocket() {
return listeningSocket;
}
void Network::setBuff(char * s) {
memset(buff, 0, DIM);
strcpy_s(buff, s);
buff[byteReceived] = 0;
buffer.clear();
buffer.assign(buff, byteReceived);
}
char * Network::getBuff() {
return buff;
}
int Network::buffLen() {
return strlen(buff);
}
string Network::getBuffer() {
return buffer;
}
// END SETTERS AND GETTERS ------------------------------------------
bool Network::Socket(int family, int type, int protocol) {
listeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if (listeningSocket == INVALID_SOCKET) {
myFormatMessage(WSAGetLastError());
return false;
}
return true;
}
void Network::sockaddr_initialize_server(const unsigned int port) {
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(port);
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
}
bool Network::Bind() {
if (bind(listeningSocket, (SOCKADDR *)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
myFormatMessage(WSAGetLastError());
closesocket(listeningSocket);
WSACleanup();
return false;
}
else
return true;
}
bool Network::Accept() {
int ret;
if ((ret = accept(listeningSocket, NULL, NULL) ) == INVALID_SOCKET) {
myFormatMessage(WSAGetLastError());
closesocket(listeningSocket);
WSACleanup();
return false;
}
else {
connectedSocket = ret;
return true;
}
}
bool Network::Listen() {
if (listen(listeningSocket, 1) == SOCKET_ERROR) {
myFormatMessage(WSAGetLastError());
closesocket(listeningSocket);
WSACleanup();
return false;
}
else
return true;
}
void Network::Recv() {
int n = recv(connectedSocket, buff, strlen(buff), 0);

setByteReceived(n);
buffer.assign(buff, n);
cout << "Buffer is: " << buff << endl;
if (byteReceived == 0)
cout << "\tConnection closed" << endl;
else if (byteReceived > 0) {
cout << "\tByte received: " << byteReceived << endl;
cout << getBuffer() << endl;
}
else {
myFormatMessage(WSAGetLastError());
}
}

void Network::CloseListeningSocket() {
if(closesocket(listeningSocket) != 0 )
cout << "Error closesocket() on listening socket." << endl;
else
cout << "Close listening socket." << endl;
}
void Network::CloseConnectedSocket() {
if (closesocket(connectedSocket) != 0)
cout << "Error closesocket() on listening socket." << endl;
else
cout << "Close listening socket." << endl;
}
void Network::Shutdown() {
if(shutdown(connectedSocket, SD_SEND) != 0)
cout << "\tError shutdown." << endl;
else
cout << "\tShutdown ok." << endl;
}

void Network::WSA_Cleanup() {
if (WSACleanup() != 0)
cout << "Failed WSACleanup()." << endl;
}




The behaviour in the end is the following: client and server are connected, the server returns 0 from recv(). I tried also to run both programs on the same machine. Thank you for your help.

jxh jxh
Answer

You have:

void Network::Recv() {
    int n = recv(connectedSocket, buff, strlen(buff), 0);
    ...

If strlen(buff) returns 0 (because buff contains a null byte at index 0), you will be asking recv() to read 0 bytes, so it will return 0 bytes. You should be using sizeof(buff) instead of strlen(buff).