我可以通过TCP发送大约10,000~2,000字节的数据吗?我正在将图像(60 x 60)从Android客户端传输到linux服务器。在Android上似乎没问题。在服务器端,如果我尝试将图片数据发送回客户端,那么它不起作用。在客户端,如果我解析,那么我得到了一些我不应该得到的奇怪数字。
通过TCP传输大数据是否有任何技术问题?我该如何解决? 提前谢谢..
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;
}
我这样得到char *并像这样发送
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;
答案 0 :(得分:5)
你要做的事情很简单(20K不是“大”)。到目前为止,最常见的原因是忽略了send
和recv
的返回代码。你应该记住一些事情:
send(2)
无法始终将所有数据从用户空间复制到内核空间。检查返回值recv
几次才能获得所有数据在实践中,在许多系统上,你可能会忘记send
大量数据(内核会嘲笑你的20K),但你必须在循环中接收。这是一个深受Stevens readn启发的功能。使用它而不是recv
ssize_t
readn(int fd, void *vptr, size_t n)
{
size_t nleft;
ssize_t nread;
char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0) {
if ((nread = read(fd, ptr, nleft)) < 0) {
if (errno == EINTR)
/* Loop back and call read again. */
nread = 0;
else
/* Some other error; can't handle. */
return -1;
} else if (nread == 0)
/* EOF. */
break;
nleft -= nread;
ptr += nread;
}
return n - nleft;
}
你似乎忘记了字数(正如Andrew Finnell怀疑的那样)。对于每个整数,您应该在发送之前(memcpy
之前)执行类似的操作:
m_dataLength = htonl(m_datalength);
收到时这是:
m_dataLength = ntohl(m_datalength);
答案 1 :(得分:2)
如果您将图像从Android发送到Linux计算机,是否说您可以成功发送和读取图像?如果没有,那么如果您的Linux服务器进程不是用Java编写的话,那么它听起来可能是一个Endian问题。
<强>更新强>
由于cnicutar有一个很好的答案,我想提供一种替代方法来手动执行你的协议。
使用它时,它会自动从主机转换为网络并返回。它还可以用于创建C ++和Java绑定。
答案 2 :(得分:0)
我认为 strace 在客户端和服务器端都有帮助。在strace日志中查找网络错误和发送/接收数据量。