2012-08-27 2 views
2

이진 데이터로 버퍼를 쉽게 채우는 함수가 있다고 가정하고 그 함수가 더 이상 사용할 버퍼를 반환하도록하려면 어떻게해야합니까?recv에서 이진 데이터로 채워진 버퍼 반환

내가 현재하고있는 방식은 (recv에서 content-length 필드를 기반으로하는) 버퍼를 작성함으로써 임시 파일을 작성한 다음 해당 임시 파일의 이름을 반환하므로 tmp 파일을 읽을 수 있습니다. 메모리에.

그러나 tmp 파일에 데이터를 쓰는 대신 데이터를 직접 반환 할 수 있으면 좋을 것입니다. 유일한 문제는 내가 이진 데이터를 반환하는 경우 버퍼의 크기가 무엇인지 알 수있는 방법이 없다는 것입니다 (정적이 아닙니다) 그래서 내 질문은 :이 이진 데이터를 돌려 줄 수있는 방법이 있습니까? 내가 그걸로 일할 수있는 어떤 방법이라도?

아니면 tmp 파일을 사용하는 것이 최선의 방법일까요?

+0

당신은 더 많은 코드를 표시해야합니다. – unwind

답변

1

는 C에서 당신은 함께 데이터 항목의 무리를 캡슐화하는 struct을 사용할 수 있습니다와 같은 함수에 그 전달 : 같은

/* Describes single I/O buffer */ 
struct buf { 
    char* data; /* pointer to dynamically allocated memory */ 
    size_t mem_size; /* allocation size */ 
    size_t data_len; /* how much data is in the buffer */ 
    struct buf* next; /* can be used for buffer chaining */ 
}; 

/* Returns 0 on success, -1 on error */ 
int read_data(int sockfd, struct buf* pb); 

또는 사용 가치 복귀 인수 :

/* buffer receives data, len tells buffer length on input, and 
* how much was read on success. */ 
int read_data(int sockfd, char* buffer, size_t* len); 
+0

매우 고맙습니다. –

2

소켓 recv와 동일한 API를 사용할 수 있습니다. 호출자는 버퍼와 max len을 제공하고 함수는 실제받은 길이를 반환합니다.

http://linux.die.net/man/2/recv

+0

나는 그것을 좋아한다! 고맙습니다! –

1

글쎄 - 임시 파일의 장점은 사실 단순한 메모리 관리입니다. 그리고 성숙한/현대적인 많은 운영체제에서/tmp와 같은 짧은 수명의 파일에 대한 오버 헤드는 아주 적습니다. 그리고 개발자가 비싸기 때문에 시간이 많이 걸립니다. 파일 크기에 대한 아이디어가 있다면 꽤 일반적인 접근 방법은 아래와 같습니다.

하지만 정확히 원하는 것은 메모리 관리에 달려 있습니다. 휠을 다시 발명하는 것도 쉽습니다. 즉 apr_socket_recv() 및 관련 메모리 관리 (http://apr.apache.org/docs/apr/1.4/group_ 4월 _network__io -

이를 방지하는 좋은 방법은 http://apr.apache.org/ 4월 커먼즈 같은 것을 사용하는 것입니다 .html # gaa6ee00191f197f64b5a5409f4aff53d1). 일반적으로 이것은 장기적인 승리입니다.

ww.

// On entry: 
//  buffp - pointer to NULL or a malloced buffer. 
//  lenp - pointer for the length; set to 0 or the length of the malloced buffer. 
// On exit 
//  return value < 0 for a fault, 0 for a connection close and > 0 for 
//  the number of bytes read. 
//  buffp will be filled out with the buffer filled; lenleftp with the bytes left 
//  (i.e not yet used). 
//  If post call *buffp != NULL you need to release/clean memory. 
// 
ssize_t sockread(..., unsigned char * * buffp , ssize_t * lenleftp) { 
     if (!buffp || !lenleftp) 
      return -1; // invalid params 

     // claim memory as needed. 
     if (*buffp == 0) { 
      *lenleftp = 16K; 
      *buffp = malloc(*lenleftp); 
     } 

     if (!*buffp || !*lenleftp) 
      return -2; // invalid params 

     ssize_t used = 0; 
     while(1) { 
     ssize_t l = recv(..., *buffp, *lenleftp - used, ..); 
     if (l < 0) { 
      // ignore transient errors we can retry without much ado. 
      if (errno == EAGAIN || errno == EINTR) 
       continue; 

      free(*buffp); *buffp = *lenleftp = NULL; 

      // report a fail. 
      return -3; 
     } 
     // we simply assume that a TCP close means we're done. 
     if (l == 0) 
      break; 

     used += l; 

     // increase buffer space as/when needed. 
     // 
     if (used >= lenleftp) { 
       *lenleftp += 32K; 
       *buffp = realloc(lenleftp); 
     }; 
    } 

    // we're assuming that a read == 0-- i.e. tcp stream done means 
    // we're done with reading. 
    // 
    *lenleftp -= used; 
    return used; 
} 
관련 문제