지금 어제 오전부터 이 시간까지 안드로이드에 네이티브 소켓을 작성 중인데, 난감한게 많네..
다른 건 어케 해결되었는데, 이상한게 있어서 좀 물어보자.
* 델파이로 서버 만들어서 안드로이드로 패킷을 [int size][data] 형식으로 보내고 있음.
* 특정 크기 미만인 경우 잘 동작하나, 순간적으로 특정 크기를 넘으면 가비지가 생기는 듯 함. 보낸 데이터를 다 읽고 없는 데이터를 또 읽음
* 작은 데이터를 간격을 두고 보내면 잘 처리됨. 아주 작은 데이터는 특정 크기만큼 순간적으로 보내도 처리됨.
아마도 루프 돌면서 보내는 동안 패킷이 조각나서 전송되었을 거 같음.
* 스마트 폰에서는 그 크기가 1400 바이트 언저리, 우분투에서는 2048 (이넘은 정확하게 재 봄)
클라이언트 소켓은 C로 블로킹하여 사용 중..
아래는 그 소스의 일부분,
if (pHandle->socket > 0) {
// Size를 수신했고, 그 크기가 0보다 크거나 같고 1MB보다 작거나 같아야 한다.
int isSizeReceived =
(recv(pHandle->socket, &pHandle->pBuffer->size, sizeof(pHandle->pBuffer->size), 0) > 0) &&
(pHandle->pBuffer->size >= 0) &&
(pHandle->pBuffer->size <= _PacketSizeLimit);
if (isSizeReceived) {
if (pHandle->pBuffer->size > 0) {
if (recv(pHandle->socket, &pHandle->pBuffer->dataStart, pHandle->pBuffer->size, 0) > 0) {
pResult = copyDataPacket(pHandle->pBuffer);
} else {
// 필요 없는 코드 그러나 확실하게 명시하기 위함
pResult = NULL;
}
} else {
pResult = copyDataPacket(pHandle->pBuffer);
}
}
// 수신 오류 발생
if (pResult == NULL) do_Disconnect(pHandle);
}
맨입으로는 안되는데요? ㅋㅋ
int isSizeReceived = (recv(pHandle->socket, &pHandle->pBuffer->size, sizeof(pHandle->pBuffer->size), 0) > 0) && (pHandle->pBuffer->size >= 0) && (pHandle->pBuffer->size <= _PacketSizeLimit);
이 코드를 보니 recv API의 반환값이 size라는 변수(pHandle->pBuffer->size)의 크기보다 작은 값이 반환되는 경우(0보다 크고 4보다 작은 값)에, pHandle->pBuffer->size의 값이 올바르지 않을 수 있는 버그가 존재하네요. 아래 코드의 recv의 반환 값도 정확히 size 값과 일치하지 않을 수도 있습니다. recv API는 주어진 버퍼의 크기와 동일하거나 그보다 작은 값을 반환하게 됩니다.
요즘 나오는 OS는 MSS(TCP Buffer의 단위 크기)가 달라서 상에서 돌아 가는 패킷의 크기가 다를 경우가 많습니다. 참고로 Windows나 Linux는 MSS 값이 기본적으로 1460바이트이고, iPhone은 이보다 몇 바이트가 더 적은 값을 가집니다. Andoind는 모르겠음. ^^
ps : host byte oder 와 network byte order 간의 변환은 안 해 주시나요? 다양한 플랫폼에서 구현하시려면 byte order 고려하심이 좋을 겁니다. ^^
땡큐!! 그 입에 몰 넣어주면 될까? ㅋㅋ 언제든 연락하셈!!
델파이하고 안드로이드 간에 엔디안 문제는 없는 거 같아서 넘어갔음.
딱 그렇게만 쓰는 프로젝트라 ㅡ.ㅡ;
안드로이드 포팅 전에 델파이로 테스트 클라이언트 만들어서 해보면 아주 잘 됨.
패킷의 크기와 상관없이..