I'm currently creating a client server application and I'm using Visual Studio 2005 and Microsoft Windows. I've been using this WINSOCK API for creating my application. I've been able to communicate and send data from my client to my server, the problem is I can only send characters and strings.
My aim is to send a 640x480 array which contain floats from my client to my server. It seems that the recv() and send() functions output are characters.
I need your help, a sample code to send a simple integer or 2x2 array to be sent will be a lot help.
you can send anything, just cast it to required format. and in the server again cast it back. it will work.
if the array is big, you may need to send it in chunks and the server should be intelegent enough to understand how much data you are sending.
see this:
client sending this structure to server: nSend = send(ClientSocket,(TCHAR*)&xi,sizeof(XINFO),0);
xi is of type xinfo, which is like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
typedefstruct xinfo
{
HWND hTree; //which tree this structure point to
SOCKET SockInfo; //which socket sending data
INFOTYPE infotype; //what info, like adding root, child etc.
FILETYPE filetype; //what kind of node is this
//directory,file,remote,cdrom etc.
DWORD nRead; //How much data send
DWORD dwSize; //File size
TCHAR szFolderPath[MAX_PATH]; //path of remote folder
TCHAR szFileName[MAX_PATH]; //name of remote file/folder
TCHAR szBuffer[READ_BUFFER];
}XINFO;
I am able to send integers however.. i cant seem to receive them right.. i'm sending an 2x2 array. Right now the client said that it was able to send the data.
the problem is that in the receiving end sometimes for example if i send the number "200" then the number "1" it receives it as "2001" the server combined the 2 data and saved it as one..
does anyone have an idea on how am i going to program the server that after receiving a certain integer it will store it immediately and not receive another one then store them both at the same time.
Network programming isn't quite the same as file I/O.
The number of client sends doesn't tie up with the server receives. TCP or UDP just sends blocks of bytes. Futher more, a router is free to split the packets into smaller manageable. In general, you need to check the return value from recv and build up the buffer until you have all the data you expect.
Your receive code should:
1. create a buffer large enough to hold your return data.
2. receive the data, looping as necessary to fill the buffer.
3. reinterpret the byte stream as the type you sent and use it.
Your send code is sending zero terminated char arrays. So the server doesn't know how much to read. If you want to send an array of integers, your code could be:
1 2 3 4 5
for(int i = 0; i < mxi; ++i)
for (int j = 0; j < mxj; ++j)
{
send(s, (char*)&data[i][j], sizeof(int), 0);
}
The receiver would be:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
for (int i = 0; i < mxi; ++i)
for (int j = 0; j < mxj; ++j)
{
int value = 0;
int nbytes = recv(s, (char*)&value, sizeof(int), 0);
if (nbytes == -1)
{
std::clog << "recv: error" << std::endl;
return nbytes;
}
elseif (nbytes != sizeof(int))
{
std::clog << "recv: unexpected fragmentation" << std::endl;
return nbytes;
}
std::cout << i << ":" << j << " = " << value << std::endl;
}
I've assumed the 4 byte block isn't going to be fragmented. I've assumed the hardware have the same endian characteristics.
I'll be adding this error checking method in to my code.. another question, in the code you just showed me.
You also used the recv() function as many times at you used the send() function, am I correct?
Meaning for ever send() there is a corresponding recv()?
In that example, yes. That's because I'm sending/receiving 4 bytes at a time, which is a very small payload that is unlikely to be fragmented, and mostly to provide you with some sample code.
Server Code:
recv(NewConnection,(char *)&sz,sizeof(int),0);
ByteReceived = recv(NewConnection,(char*)&testimage, sz, 0);
the FinalImage1 is a [720][480] array and thus the send buffer turns out to be around 600kb when i use sizeof. So I am expecting to receive a 600kb data to the server.
The problem is when I view the return in the send function it value is -1.
So that means I just sent -1 number of bytes? or is does this mean that I got an error in the send function? If so i assume I sent to much data in one send function that why I got an error?
If I where to divide my data to smaller packets, how do I do that? Do I use for loop?
and is there a limit on how much data can I send in one send() function?
I need to transfer this 720x486 array to the server.
Mind if I ask on how am I suppose to do that? I'm thinking that I should be using pointers? But I don't know how to do that just yet.
If I where to use for loop like so..
for(int i = 0; i < mxi; ++i)
for (int j = 0; j < mxj; ++j)
{
send(s, (char*)&data[i][j], sizeof(int), 0);
}
like your previous example. I would be sending about 8bytes per send if I where sending doubles right? so how am I going send chunks at a time. for example 16k chucks?
I tried to use that for loop style before.. I send one double per send and repeated it for like 600k times but in about 10k or less my pc crashed. so i guess I should not be using this kind of technique. I should be sending data in huge chucks but I don't know how to do that. I'm still reading on pointers right now.
Help please.. any examples or tips are surely to be appreciated.
for (char* p = FinalImage1, end = data + sizeof(FinalImage1); p < end; )
{
int blocksz = std::min(16*1024, end - p);
int sent = send(s, p, blocksz; 0); // corrected, the block to send starts at p
if (sent <= 0)
break;
p += sent;
}
So "p" and "end" are pointers, right?
if I understand this correctly, the loop will continue until the value of "p" is equal to "end"?
and blocksz returns the value which is lesser from 16*1024 and "end-p" thus, choosing which is lesser to be the size for the send function.
this is just for error checking, right?
------------------
if (sent <= 0)
break;
------------------
and I get it that the value of sent is added to the begin.
My question is, what is "data" and why is end=data + sizeof(FinalImage1)?
I'm assuming "data" is also "sizeof(FinalImage1)"?
and the second value in the send() function is suppose to be the data right? I don't know what to put there?
"begin" is an undeclared variable. should I put "FinalImage1" there or "p"?
I'm really confused, I'm new in using pointers. Forgive me for the questions.
It assimes the data to be sent is in a fixed variable called FinalImage1, which I got from your code above. The code loops sending the next chunk each time until it's all gone.
Server Code:
recv(NewConnection,(char *)&sz,sizeof(int),0);
ByteReceived = recv(NewConnection,(char*)&testimage, sz, 0);
So now I have multiple send() functions occurring because of the loop, my client is sending small packets. 1st my client is going to send the size of the whole data which is "sz" the it will now send the multiple small packets.
what happening now is i'm using just one recv() with a large buffer to accept the multiple small send().
The problem now is my server stops receiving packets even if the client is not yet finished sending.