[C++ 소켓 프로그래밍 버퍼문제 어떤 방식으로 풀어나가야 할까요?] -> [IplImage를 char형 배열로 전환하는 방법이 없을까요?]

corona89의 이미지

[ 이 질문은 해결되었습니다. 밑의 질문을 봐주시면 감사하겠습니다. ]
제가 이미지를 교환하는 서버 프로그램과 클라이언트 프로그램을 만들고 있는데
데이터 전송에서 문제가 발생합니다.

제가 프로그래밍 한 방식은
버퍼 사이즈를 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의 이미지

send 함수의 return값이 BUFFER_SIZE보다 작을 수 있습니다(전송이 성공한다는 가정하에서도).
recv 함수도 마찬가지입니다. socket이 끊겼을 때

recv(*socket, &ack, 1, RECVFLAG);

이 함수를 실행하고 나서는 recv는 SOCKET_ERROR(-1) 값을 반환하며 ack 값은 변하지 않게 됩니다.

결론 : send 및 recv 함수의 return 값을 확인(로그로 찍는다던지)해 보세요.

corona89의 이미지

답변 감사합니다.
확실히 ack에서도 에러가 발생할 수 있을거 같네요.

제가 이미지파일이 아닌 char형 데이터를 만들어서 테스트 해봤는데
char형 데이터는 제대로 전송을 하더군요.
send 함수의 문제가 아닌 IplImage 데이터를 char로 바꾸면서 문제가 생긴 것 같습니다.

IplImage 가 구조체 자료형인데
이것을 reinterptret_cast(iplImagedata) 을 이용해서 casting 한 후
보내는 도중 데이터를 읽지 못하고 소켓 에러가 뜨는 것 같습니다.

mirheekl의 이미지

파일로 저장한 뒤에 해당 파일을 전송하라는 조언이 많은 것 같습니다. 저장속도 등이 문제가 된다면 파일 대신 메모리 객체로. 100% 동일한 데이터를 얻으려면 손실압축을 사용하지 않는 포맷으로 저장해야 되겠지요.

시리얼라이제이션을 통해서 하셔도 되지만 어차피 근본적으론 거의 같은 작업. C++에선 시리얼라이제이션 관련 함수가 있다 해도 껍데기뿐이고 결국에는 누군가가 직접 구현해줘야 하거든요.

아래 링크가 그 작업의 한 예가 되겠네요.

http://www.barbato.us/2011/06/06/blfilestorage-simple-class-serializeunserialize-iplimage-opencv/

--

corona89의 이미지

위의 방식대로 구현하면 구현이 쉬울 것 같네요.
하지만 지금 만들고 있는 프로그램은 정말 많은 이미지 데이터를 보내줘야 되서 퍼포먼스가 나올지...
한번 만들어서 테스트 해 보고 결정해봐야 될 것 같습니다.

역시 제가 생각하지 못한 것들을 아시는 분들이 많아서 항상 KLDP 게시판 올때마다 항상 배우고 가네요.
답변 감사드립니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.