Can I send about 10,000 ~ 20,000 bytes data over TCP? I am transferring an image (60 by 60) from Android client to linux server. On android it seems ok. On server side, if I try to send the picture data back to client, then it doesn’t work. On client side, if I parse then I got some weird number that I shouldn’t get.
Is there any technical problem of transferring a big data over TCP? How do I fix this?
Thanks in advance..
char* PictureResponsePacket::toByte(){
/*
* HEADER
*
* Magic number (4)
* Data length (4)
* Packet Id (2)
* Packet type (2)
* Device Id (48)
*
*/
/*
* BODY
*
* Nickname (48)
* deviceId (4)
* m_pictureSize
*/
int offset = 0;
int headerLength = sizeof(int) + sizeof(int) + sizeof(short) + sizeof(short) + 48;
int bodyLength = 48 + 4 + m_pictureSize;
int dataLength = headerLength + bodyLength;
m_dataLength = dataLength;
log("PictureResponsePacket::toByte(), data length %d \n", m_dataLength);
char *sendBuffer = new char[dataLength];
memset(sendBuffer, 0x00, dataLength);
char *ptr = sendBuffer;
/*
* -------------
* HEADER
* -------------
*/
/*
* Magic number
*/
memcpy(ptr + offset, m_magicNumberBuffer, sizeof(int));
offset += sizeof(int);
/*
* Data length
*/
memcpy(ptr + offset, &m_dataLength, sizeof(int));
offset += sizeof(int);
/*
* Packet id
*/
memcpy(ptr + offset, &m_packetId, sizeof(short));
offset += sizeof(short);
/*
* Packet type
*/
memcpy(ptr + offset, &m_packetType, sizeof(short));
offset += sizeof(short);
/*
*Device Id
*/
memcpy(ptr + offset, m_deviceId.c_str(), m_deviceId.size());
offset += 48;
/*
* -------------
* BODY
* -------------
*/
memcpy(ptr + offset, m_senderDeviceId.c_str(), m_senderDeviceId.size());
offset += 48;
memcpy(ptr + offset, &m_pictureSize, sizeof(int));
offset += sizeof(int);
memcpy(ptr + offset, m_pictureData, m_pictureSize);
offset += m_pictureSize;
return sendBuffer;
}
I am getting char* this way and sending it like this
char * sBuffer = reponsePacket->toByte();
int remainLength = reponsePacket->getDataLength();
int currentSentLength = 0;
SocketClient *client = work->getClient();
while(remainLength > 0){
if(remainLength >= MAX_LENGTH)
currentSentLength = send(client->getFd(), sBuffer, MAX_LENGTH, MSG_NOSIGNAL);
else
currentSentLength = send(client->getFd(), sBuffer, remainLength, MSG_NOSIGNAL);
if(currentSentLength == -1){
log("WorkHandler::workLoop, connection has been lost \n");
break;
}
sBuffer += currentSentLength;
remainLength -= currentSentLength;
What you are trying to do is easy (20K is not “big”). By far the most common reason something like this happens, is disregarding the return codes of
sendandrecv. You should keep a few things in mind:send(2)can’t always copy all the data from user space to kernel space. Check the returned valuerecva few times before getting all of itIn practice, on many systems you might get away with
sending large amounts of data (the kernel will laugh at your 20K) but you will have to receive in a loop. Here is a function heavily inspired by Stevens readn. Use it instead ofrecvEDIT
You seem to be forgetting about endianness (as Andrew Finnell suspected). For every integer, you should do something like this before sending (before
memcpy):And this when receiving: