2

バッファをバイナリデータで簡単に埋める関数があると仮定すると、その関数がバッファを返してさらに使用できるようにするにはどうすればよいですか?

私が現在行っている方法は、(recv の content-length フィールドに基づいて) バッファーに書き込み、一時ファイルを書き込み、その一時ファイルの名前を返すことで、tmp ファイルをメモリに読み込むことができるようにすることです。

ただし、データを tmp ファイルに書き込んで使用するのではなく、データを直接返すことができればいいのですが。唯一の問題は、バイナリ データを返す場合です。バッファのサイズを知る方法がありません (静的ではありません)。したがって、私の質問は、このバイナリ データを返す方法とサイズを返す方法があるか、または私がそれを扱うことができる方法はありますか?

それとも、tmp ファイルの使用に固執するのが最善の策ですか?

4

3 に答える 3

2

socket recv と同じ API を使用できます。呼び出し元はバッファと最大長を提供し、関数は実際に受信した長さを返します。

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

于 2012-08-27T19:11:19.527 に答える
1

ええと、一時ファイルの利点は確かに、メモリ管理が簡単になることです。また、多くの成熟した/最新のオペレーティング システムでは、/tmp にあるような短命のファイルのオーバーヘッドはごくわずかです (そして、開発者としての時間は高くつきます)。ファイルサイズについて何らかの考えがある場合、かなり一般的なアプローチは以下のようなものです。

しかし、まさにあなたが望むものはメモリ管理に依存します。そして、車輪を再発明するのは簡単です。

これを回避する良い方法は、http://apr.apache.org/ APR Commons のようなものを使用することです。つまりapr_socket_recv() と関連するメモリ管理 (http://apr.apache.org/docs/apr/1.4/) group_ apr _network__io.html#gaa6ee00191f197f64b5a5409f4aff53d1)。一般的に、それは長期的な勝利です。

Dw。

// 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;
}
于 2012-08-27T19:29:06.683 に答える
1

C では、次のように、 aを使用し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 );
于 2012-08-27T19:20:31.673 に答える