Jump to: navigation, search

Table of Contents >> Programmer's Reference

#include <trsocket.h>

int tfZeroCopyRecv (
int socketDescriptor,
ttUserMessage TM_FAR * bufferHandlePtr,
char TM_FAR * TM_FAR * dataPtrPtr,
int maxDataLength,
int flags

Function Description

This function is used to recv a zero copy message. It operates identically to recv with the exception that it takes a zero copy buffer handle as a parameter and puts the beginning of the data into a passed pointer. However, it does not support the MSG_OOB flag, since there is only one byte of out-of-band data, and it would be inefficient to use the tfZeroCopyRecv() in that case. To recv out-of-band data, the recv() call should be used instead.

Note Note: The user must call tfFreeZeroCopyBuffer() in order to free the buffer after the user has finished with it.


  • socketDescriptor
    The socket descriptor to receive data from.
  • bufferHandlePtr
    The zero copy buffer that contains the message.
  • dataPtrPtr
    A pointer ot a (char *) of the beginning of the stored data.
  • maxDataLength
    The length of the message.
  • flags
    See below for possible flags parameters that can be OR'ed together.


Value Meaning
MSG_DONTWAIT Don't wait for data, but rather return immediately.
MSG_PEEK "Peek" at the data present on the socket; the data is returned, but not consumed, so that a subsequent receive operation will see the same data.
MSG_SCATTERED (Non-TCP sockets). If the receive data is scattered, it will be passed to the user as is, and will not get copied into a new buffer to make the data contiguous. Upon return, bufferHandlePtr will point to a scattered buffer, as explained below.


When the MSG_SCATTERED bit is set in the flags parameters, then upon successful return from tfZeroCopyRecv(), the bufferHandlePtr parameter should be cast to a pointer to a ttUserPacket structure, where ttUserPacket is defined as follows:

#define trsocket.h
 * Data type used for the linked list of packets passed to the device
 * driver single call scattered send function prototype.
typedef struct tsUserPacket
/* Next tsUserPacket for scattered data  */
/*    struct tsUserPacket TM_FAR   *pktuLinkNextPtr; */
    void               TM_FAR   *pktuLinkNextPtr;
/* Pointer to data */
    ttUser8BitPtr                pktuLinkDataPtr;
#ifdef TM_DSP
/* byte offset of start of data, in word pointed to by pktuLinkDataPtr */
    int                          pktuLinkDataByteOffset;
#endif /* TM_DSP */
#if defined(TM_DEV_SEND_OFFLOAD) || defined(TM_DEV_RECV_OFFLOAD)
    ttUserVoidPtr                pktuDevOffloadPtr;
/* Size of data pointed by pktuLinkDataPtr */
    ttPktLen                     pktuLinkDataLength;
 * Total packet length (of chained scattered data). Valid in first link
 * only
    ttPktLen                     pktuChainDataLength;
 * Number of links linked to this one (not including this one).
 * Valid in first link only.
    int                          pktuLinkExtraCount;
/* User-defined data */
    ttUserGenericUnion           pktuUserParam;
#endif /* TM_USE_USER_PARAM */
} ttUserPacket;
typedef ttUserPacket TM_FAR * ttUserPacketPtr;


The following code extract shows how to navigate a scattered recv buffer, and copies it into bufferArray[].

#define TM_BUF_ARRAY_SIZE     3000
char bufferArray[TM_BUF_ARRAY_SIZE];
            retCode = tfZeroCopyRecv(ssd,
            if (retCode > 0)
                recvdLength += retCode;
                tm_assert(testzUdpToFrom, retCode == sendDataLength);
void scatteredRecvCopyNCheck(ttUserMessage recvMessageHandle,
                             ttUser8BitPtr dataPtr,
                             ttPktLen      msgLength)
    ttUserPacketPtr     recvPacketUPtr;
    char              * bufferPtr;
    int                 extraCount;
    extraCount = -1;
    recvPacketUPtr = (ttUserPacketPtr)recvMessageHandle;
    bufferPtr = &bufferArray[0];
    tm_assert(testzUdp, msgLength == recvPacketUPtr->pktuChainDataLength);
    tm_assert(testzUdp, msgLength <= sizeof(bufferArray));
    tm_assert(testzUdp, dataPtr == recvPacketUPtr->pktuLinkDataPtr);
        tm_assert(testzUdp, msgLength >= recvPacketUPtr->pktuLinkDataLength);
                  (recvPacketUPtr->pktuLinkDataPtr != (ttUser8BitPtr)0));
        bufferPtr += recvPacketUPtr->pktuLinkDataLength;
        msgLength -= recvPacketUPtr->pktuLinkDataLength;
        recvPacketUPtr = recvPacketUPtr->pktuLinkNextPtr;
    while (   (msgLength != (ttPktLen)0) 
           && (recvPacketUPtr != (ttUserPacketPtr)0) );
    tm_assert(testzUdp, msgLength == 0);
    recvPacketUPtr = (ttUserPacketPtr)recvMessageHandle;
    tm_assert(testzUdp, extraCount == recvPacketUPtr->pktuLinkExtraCount);

Note Note: See also tfZeroCopySend().


  • >= 0
    The number of bytes received.

Note Note: TM_SOCKET_ERROR means that this socket call has failed and the errorCode has been set on the socket itself.

To retrieve the socket error the user must call tfGetSocketError(socketDescriptor).

Possible socket errors

    The socket descriptor is invalid.
    The socket requires that the message be received atomically and bufferLength was too small.
    The socket is marked as non-blocking or the MSG_DONTWAIT flag is used and no data is available to be read.
    The remote socket has closed the connection and there is no more data to be received (TCP socket only).
    One of the parameters is invalid.
    The socket is not connected.

Table of Contents >> Programmer's Reference