[C++ 소켓 프로그래밍 버퍼문제 어떤 방식으로 풀어나가야 할까요?] -> [IplImage를 char형 배열로 전환하는 방법이 없을까요?]
[ 이 질문은 해결되었습니다. 밑의 질문을 봐주시면 감사하겠습니다. ]
제가 이미지를 교환하는 서버 프로그램과 클라이언트 프로그램을 만들고 있는데
데이터 전송에서 문제가 발생합니다.
제가 프로그래밍 한 방식은
버퍼 사이즈를 5000정도 주고
만약 100012 바이트를 보낸다면
이것을 21(100012 = 5000 * 20 + 12)개로 분할해서 send() 하도록 만들었습니다.
// send the data
size = tot_size / BUFFER_SIZE;
for (i = 0; i < size ; i++)
{
int send_size = send(*socket, &data[i*BUFFER_SIZE], BUFFER_SIZE, SENDFLAG);
if (send_size == -1)
{
std::cout << WSAGetLastError() << std::endl;
}
recv(*socket, &ack, 1, RECVFLAG);
if (ack == 1)
{
i--;
ack = 0;
}
}
// send the last data
while ( tot_size % BUFFER_SIZE != 0 )
{
send(*socket, &data[(i + 1)*BUFFER_SIZE], tot_size % BUFFER_SIZE, SENDFLAG);
recv(*socket, &ack, 1, RECVFLAG);
if (ack == 0) break;
else ack = 0;
}
하지만 문제는 한 12번째 쯤의 send() 에서
WSAEFAULT 10014 와 같은 에러가 발생한다는 것 입니다.
에러 메세지를 봐도, 제 경험으로 생각해 봐도... 버퍼가 꽉차서 생기는 문제인 것 같은데 해결할 방법을 못찾겠습니다.
제가 해본 방법은
1. error가 발생하면 send() 함수를 다시 호출한다. : 반복되는 에러 발생으로 실패.
2. error가 발생하면 recv()를 이용해서 버퍼를 비운다. : 아무 영향을 끼치지 않음...
많은 도움 부탁드립니다.
----------------------------------------------------------------------------------------------------------------
[IplImage를 char형 배열로 전환하는 방법이 없을까요?]
위의 내용은 잘못된 데이터를 전송해서 발생하는 오류였습니다.
이때 보낸 잘못된 데이터가
reinterpret_cast(IplImage데이터) 이렇게 해서 발생했는데
혹시 IplImage 자체를 전송하는 방법은 없을까요?
C#같은 경우에는 class를 serialize 해서 보내는 방법이 있었는데
C++ 에서는 못찾겠네요.
IplImage->imageData 만 전송하는 방법도 있으나 IplImage 전체를 보내고 싶은데 방법을 모르겠네요.
C++ 에서 클래스를 serialize 하는 함수가 있나요?
gilgil.net
send 함수의 return값이 BUFFER_SIZE보다 작을 수 있습니다(전송이 성공한다는 가정하에서도).
recv 함수도 마찬가지입니다. socket이 끊겼을 때
이 함수를 실행하고 나서는 recv는 SOCKET_ERROR(-1) 값을 반환하며 ack 값은 변하지 않게 됩니다.
결론 : send 및 recv 함수의 return 값을 확인(로그로 찍는다던지)해 보세요.
www.gilgil.net
답변 감사드립니다.
답변 감사합니다.
확실히 ack에서도 에러가 발생할 수 있을거 같네요.
제가 이미지파일이 아닌 char형 데이터를 만들어서 테스트 해봤는데
char형 데이터는 제대로 전송을 하더군요.
send 함수의 문제가 아닌 IplImage 데이터를 char로 바꾸면서 문제가 생긴 것 같습니다.
IplImage 가 구조체 자료형인데
이것을 reinterptret_cast(iplImagedata) 을 이용해서 casting 한 후
보내는 도중 데이터를 읽지 못하고 소켓 에러가 뜨는 것 같습니다.
좀 찾아보니..
파일로 저장한 뒤에 해당 파일을 전송하라는 조언이 많은 것 같습니다. 저장속도 등이 문제가 된다면 파일 대신 메모리 객체로. 100% 동일한 데이터를 얻으려면 손실압축을 사용하지 않는 포맷으로 저장해야 되겠지요.
시리얼라이제이션을 통해서 하셔도 되지만 어차피 근본적으론 거의 같은 작업. C++에선 시리얼라이제이션 관련 함수가 있다 해도 껍데기뿐이고 결국에는 누군가가 직접 구현해줘야 하거든요.
아래 링크가 그 작업의 한 예가 되겠네요.
http://www.barbato.us/2011/06/06/blfilestorage-simple-class-serializeunserialize-iplimage-opencv/
--
감사합니다. 위의 링크에서 설명하는 방법데로 하면 쉽게 구현이 가능할 것 같습니다.
위의 방식대로 구현하면 구현이 쉬울 것 같네요.
하지만 지금 만들고 있는 프로그램은 정말 많은 이미지 데이터를 보내줘야 되서 퍼포먼스가 나올지...
한번 만들어서 테스트 해 보고 결정해봐야 될 것 같습니다.
역시 제가 생각하지 못한 것들을 아시는 분들이 많아서 항상 KLDP 게시판 올때마다 항상 배우고 가네요.
답변 감사드립니다.
댓글 달기