Click to See Complete Forum and Search --> : Getting ALL data


ccubed
June 25th, 2007, 04:27 AM
Okay, i currently have a recv command that get's 512 bytes at any time, however, in most cases the server wants to send me more then that. how do I enter a loop with recv until i get ALL of the data the server wants to send me? this is what i have currently (it's the bool get_data function).


/*
Nova Client
Created: June 22, 2007
Last Updated: June 22, 2007
Description: This file contains all the socket functions this client uses
*/

#include <winsock.h>
#include <windows.h>
#include <iostream>
#include <string>

//a socket class
class novasock{

public:

void sock_info( int num, std::string hostn, novasock &NSock){

port = num;
address = hostn;

}

bool get_data( novasock &NSock ){

NSock.datasize = recv( Nova, NSock.buffer_in, 512, 0);

if ( NSock.datasize > 0 ){

std::cout << "#DEBUG: " << NSock.datasize << " Bytes received." << std::endl;

printf("%s\n",NSock.buffer_in);

return true;

}
else if( NSock.datasize == 0 ){

std::cout << "#debug: No data to receive" << std::endl;

return true;

}
else{

return false;

}

}

bool send_data( novasock &NSock ){

if ( sizeof( NSock.out ) >= 1 ){

NSock.datasize = send( Nova, NSock.out.c_str(), sizeof( NSock.out ), 0 );

std::cout << "#DEBUG: " << NSock.datasize << " Bytes sent." << std::endl << "#DEBUG:SENT: " << NSock.out << " . " << std::endl;

return true;

}
else{

return false;

}

}

bool open_socket( novasock &NSock ){

NSock.WVer = MAKEWORD(1,1);

NSock.error_ret = WSAStartup( NSock.WVer, &NSock.WsaData );

if ( NSock.error_ret != NO_ERROR ){

std::cout << "#Couldn't Initilize Socket. Error " << NSock.error_ret << " returned." << std::endl;

return false;
}

Nova = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );

if ( Nova == INVALID_SOCKET ){

printf("socket failed with error: %ld\n", WSAGetLastError());

return false;

}

if ( Nova != INVALID_SOCKET){

NSock.LPHostEnt = gethostbyname(NSock.address.c_str());
NSock.sin.sin_family = AF_INET;
NSock.sin.sin_addr = *((LPIN_ADDR)*NSock.LPHostEnt->h_addr_list);
NSock.sin.sin_port=htons(NSock.port);

}

if ( NSock.LPHostEnt == NULL ){

std::cout << "Couldn't find " << NSock.address << "." << std::endl;

return false;

}
if ( connect( Nova, (SOCKADDR*) &NSock.sin, sizeof(NSock.sin) ) == SOCKET_ERROR ){

std::cout << "Error Connecting to " << NSock.address << "." << std::endl;

return false;

}

return true;
}

void close_Nsock(){

closesocket(Nova);

}

char buffer_in[512]; //these two are used too much to be private
std::string out;

private:

int port;
int datasize;
int error_ret;
LPHOSTENT LPHostEnt;
WSADATA WsaData;
WORD WVer;
std::string address;
SOCKET Nova;
struct sockaddr_in sin;
struct hostent host;

};

ahoodin
June 25th, 2007, 08:28 AM
Something like this works. Depending on your packet scheme, it may be preferable to send message size in the first bytes of your packet, like a header.

int totaldatasize=99999;//crazy default size
while (totrcv < totaldatasize)
{
bytesrcv = recv( Nova, NSock.buffer_in, BUFSZ, 0);
if (bytesrcv < 0)
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
DieWithError(WSAGetLastError());
}
else
totrcv = bytesrcv;
if (totrcv >= 10 && totaldatasize==99999)
{
totaldatasize = *(int*)& NSock.buffer_in[6];
}
}
NSock.datasize = totrcv;

HTH,

ahoodin

MikeAThon
June 25th, 2007, 11:54 AM
If you are designing both client and server, then ahoodin is right: prefix each send() with an integer that tells the recipient how many bytes follow. This is a protocol that's easy to understnad, use and implement.

I don't understand his sample code, however. Why is he testing against a received size of 10, and why is the integer found at NSock.buffer_in[6]?

Mike

ahoodin
June 25th, 2007, 04:44 PM
Mike thats that is an arbitrary example. If you dont like it, I am sorry, but I believe ccubed should make up his own message format.

MikeAThon
June 25th, 2007, 04:52 PM
Ah, sorry, I understand now.

ccubed
June 25th, 2007, 05:41 PM
Thanks. Anyways, I am not designing the server. It's a mud client so i've never incountered a mud (ESPECIALLY MUSHES!) intro that's less then 512 bytes . :P