⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bsdsocklib.c

📁 vxworks的完整的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
            bsdSockAddrRevert (from);            }	}    if (mfrom != NULL)        m_freem (mfrom);    splx (spl);    if (status)        {        if (usrIo.uio_resid != len &&            (status == EINTR || status == EWOULDBLOCK))            status = OK;        }    return (status == OK ? (len - usrIo.uio_resid)  : ERROR);    }/********************************************************************************* bsdRecv - receive data from a socket** This routine receives data from a connection-based (stream) socket.** The maximum length of <buf> is subject to the limits on TCP buffer* size; see the discussion of SO_RCVBUF in the setsockopt() manual* entry.* * RETURNS* The number of bytes received, or ERROR if the call fails.* * SEE ALSO* setsockopt()** NOMANUAL*/int recv    (    FAST int    s,      /* socket to receive data from */    FAST char   *buf,   /* buffer to write data to */    FAST int    bufLen, /* length of buffer */    FAST int    flags   /* flags to underlying protocols */    )    {    FAST struct socket	*so;    FAST int		spl;    FAST int		status;    int			len;    struct uio		usrIo;		/* user IO structure */    struct iovec	ioVec;		/* IO vector structure */    int			soFlags;    struct mbuf **	ppRcvMbuf = NULL;	/* for zero copy interface */    /* extract the socket from the fd */    if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR)        return (ERROR);#ifdef VIRTUAL_STACK    if (stackInstFromSockVsidSet (s) != OK)        return (ERROR);#endif    /* VIRTUAL_STACK */        spl = splnet ();    usrIo.uio_iov = &ioVec;    usrIo.uio_iovcnt = 1;    usrIo.uio_offset = 0;    usrIo.uio_resid = bufLen;    usrIo.uio_segflg = UIO_USERSPACE;    usrIo.uio_rw = UIO_READ;    ioVec.iov_base = (caddr_t) buf;    ioVec.iov_len = bufLen;    soFlags = flags;    if (flags & MSG_MBUF)		/* if zero copy interface enabled */	ppRcvMbuf = (struct mbuf **)buf;    len = usrIo.uio_resid;    status = soreceive (so, (struct mbuf **)NULL, &usrIo, ppRcvMbuf, 			(struct mbuf **)0, &soFlags);    splx (spl);    if (status)        {        if (usrIo.uio_resid != len &&            (status == EINTR || status == EWOULDBLOCK))            status = OK;        }    return (status == OK ? (len - usrIo.uio_resid)  : ERROR);    }/********************************************************************************* bsdSockRead - read from a socket** bsdSockRead is called by the I/O system to do a read on a socket.*/LOCAL int bsdSockRead    (    FAST struct socket  *so,    FAST caddr_t        buf,    FAST int            bufLen    )    {    FAST int spl;    FAST int status;    int len;    struct uio		usrIo;		/* user IO structure */    struct iovec	ioVec;		/* IO vector structure */    int			soFlags = 0;#ifdef VIRTUAL_STACK    if (stackInstFromSockVsidSet (so->so_fd) != OK)        return (ERROR);#endif    /* VIRTUAL_STACK */        spl = splnet ();    usrIo.uio_iov = &ioVec;    usrIo.uio_iovcnt = 1;    usrIo.uio_offset = 0;    usrIo.uio_resid = bufLen;    usrIo.uio_segflg = UIO_USERSPACE;    usrIo.uio_rw = UIO_READ;    ioVec.iov_base = (caddr_t) buf;    ioVec.iov_len = bufLen;    len = usrIo.uio_resid;    status = soreceive (so, (struct mbuf **)NULL, &usrIo, (struct mbuf **)0, 			(struct mbuf **)0, &soFlags);    splx (spl);    if (status)        {        if (usrIo.uio_resid != len &&            (status == EINTR || status == EWOULDBLOCK))            status = OK;        }    return (status == OK ? (len - usrIo.uio_resid)  : ERROR);    }/********************************************************************************* bsdRecvmsg - receive a message from a socket** This routine receives a message from a datagram socket.  It may be used in* place of recvfrom() to decrease the overhead of breaking down the* message-header structure `msghdr' for each message.** RETURNS* The number of bytes received, or ERROR if the call fails.** NOMANUAL*/int recvmsg    (    int                 sd,     /* socket to receive from */    struct msghdr       *mp,    /* scatter-gather message header */    int                 flags   /* flags to underlying protocols */    )    {    FAST struct iovec 	*iov;    FAST struct iovec   * pIovCopy; /* kernel copy of user iov */    FAST int 		ix;    caddr_t		namelenp;    caddr_t		controllenp;    struct socket	*so;    struct uio 		auio;    struct iovec        aiov [UIO_SMALLIOV];  /* use stack for small user iov */    struct mbuf 	*from = NULL;    struct mbuf		*control = NULL;    int 		len;    int 		status;    int 		slev;    BOOL                mallocedIov;    /* TRUE if kernel iov copy malloced */                                        /* from system pool */    int                 recvLen;        /* length of received message */    if (flags & MSG_MBUF)	{        netErrnoSet (EINVAL);        return (ERROR);			/* mbuf uio not supported */	}    /* extract the socket from the fd */    if ((so = (struct socket *) iosFdValue (sd)) == (struct socket *) ERROR)        return (ERROR);#ifdef VIRTUAL_STACK    if (stackInstFromSockVsidSet (sd) != OK)        return (ERROR);#endif    /* VIRTUAL_STACK */        /* allocate space to copy user struct iovec */    if (mp->msg_iovlen >= UIO_SMALLIOV)	{	if (mp->msg_iovlen >= UIO_MAXIOV)	    {	    netErrnoSet (EMSGSIZE);	    return (ERROR);	    }	MALLOC (pIovCopy, struct iovec *, 		sizeof (struct iovec) * mp->msg_iovlen, MT_DATA, M_WAIT);	if (pIovCopy == NULL)	    {	    netErrnoSet (ENOBUFS);	    return (ERROR);	    }	mallocedIov = TRUE;	}    else	{	pIovCopy = aiov;	mallocedIov = FALSE;	}    slev = splnet ();    namelenp	= (caddr_t) &mp->msg_namelen;    controllenp	= (caddr_t) &mp->msg_controllen;    mp->msg_flags = flags;        auio.uio_iov        = pIovCopy;    auio.uio_iovcnt 	= mp->msg_iovlen;    auio.uio_segflg 	= UIO_USERSPACE;    auio.uio_offset	= 0;    auio.uio_resid 	= 0;    auio.uio_rw 	= UIO_READ;    iov 		= mp->msg_iov;    for (ix = 0; ix < mp->msg_iovlen; ix++, iov++)        {        if (iov->iov_len < 0)            {            netErrnoSet (EINVAL);	    splx (slev);	    if (mallocedIov)		{		FREE (pIovCopy, MT_DATA);		}            return (ERROR);            }        if (iov->iov_len == 0)            continue;		pIovCopy->iov_len = iov->iov_len;	pIovCopy->iov_base = iov->iov_base;	pIovCopy++;        auio.uio_resid += iov->iov_len;        }    /* Save a pointer to struct iovec copy */    pIovCopy = auio.uio_iov;    len = auio.uio_resid;    status = soreceive (so, &from, &auio, (struct mbuf **)0, 			mp->msg_control ? &control : (struct mbuf **)0,			&mp->msg_flags);        recvLen = len - auio.uio_resid;    if (mp->msg_name)        {        len = mp->msg_namelen;        if (len <= 0 || from == 0)            len = 0;        else            {            if (len > from->m_len)                len = from->m_len;            (void) copyout((caddr_t) mtod(from, caddr_t),			   (caddr_t) mp->msg_name, len);            }        (void) copyout ((caddr_t) &len, namelenp, sizeof (int));        if (bsdSock43ApiFlag)            {            /* Convert the address structure contents to the BSD 4.3 format. */            bsdSockAddrRevert ((struct sockaddr *)mp->msg_name);            }        }    if (mp->msg_control)        {        len = mp->msg_controllen;        if (len <= 0 || control == 0)            len = 0;        else            {            if (len > control->m_len)                len = control->m_len;            (void) copyout ((caddr_t) mtod(control, caddr_t),			    (caddr_t) mp->msg_control, len);            }        (void) copyout ((caddr_t) &len, controllenp, sizeof (int));        }    /* If status has been set to EINVAL in TCP, then TCP has freed the     * mbufs. We do not free the mbufs, we return the errno     * to the application.     */    if (status == EINVAL)	{	netErrnoSet (status);	splx (slev);	if (mallocedIov)	    {	    FREE (pIovCopy, MT_DATA);	    }	return (ERROR);	}    /* if status is not EINVAL, we free the mbufs as TCP has not freed it */    if (control)        m_freem(control);    if (from)        m_freem(from);    splx (slev);    if (mallocedIov)	{	FREE (pIovCopy, MT_DATA);	}    if (status)	{        if (auio.uio_resid != len &&            (status == EINTR || status == EWOULDBLOCK))            status = OK;	}    return (status == OK ? recvLen : ERROR);    }/********************************************************************************* bsdSetsockopt - set socket options** This routine sets the options associated with a socket.* To manipulate options at the "socket" level, <level> should be SOL_SOCKET.* Any other levels should use the appropriate protocol number.** OPTIONS FOR STREAM SOCKETS* The following sections discuss the socket options available for* stream (TCP) sockets.** .SS "SO_KEEPALIVE -- Detecting a Dead Connection"* Specify the SO_KEEPALIVE option to make the transport protocol (TCP)* initiate a timer to detect a dead connection:* .CS*     setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof (optval));* .CE* This prevents an application from  hanging on an invalid connection. * The value at <optval> for this option is an integer (type `int'),* either 1 (on) or 0 (off).* * The integrity of a connection is verified by transmitting* zero-length TCP segments triggered by a timer, to force a response* from a peer node.  If the peer does not respond after repeated* transmissions of the KEEPALIVE segments, the connection is dropped,* all protocol data structures are reclaimed, and processes sleeping* on the connection are awakened with an ETIMEDOUT error.* * The ETIMEDOUT timeout can happen in two ways.  If the connection is* not yet established, the KEEPALIVE timer expires after idling* for TCPTV_KEEP_INIT.  If the connection is established, the* KEEPALIVE timer starts up when there is no traffic for* TCPTV_KEEP_IDLE.  If no response is received from the peer after* sending the KEEPALIVE segment TCPTV_KEEPCNT times with interval* TCPTV_KEEPINTVL, TCP assumes that the connection is invalid.* The parameters TCPTV_KEEP_INIT, TCPTV_KEEP_IDLE, TCPTV_KEEPCNT, and* TCPTV_KEEPINTVL are defined in the file vw/h/net/tcp_timer.h.** .SS "SO_LINGER -- Closing a Connection"* Specify the SO_LINGER option to determine whether TCP should perform a  * "graceful" close:* .CS*     setsockopt (sock, SOL_SOCKET, SO_LINGER, &optval, sizeof (optval));* .CE* For a "graceful" close, when a connection is shut down TCP tries* to make sure that all the unacknowledged data in transmission channel* are acknowledged, and the peer is shut down properly, by going through an* elaborate set of state transitions.* * The value at <optval> indicates the amount of time to linger if* there is unacknowledged data, using `struct linger' in* vw/h/sys/socket.h.  The `linger' structure has two members:* `l_onoff' and `l_linger'.  `l_onoff' can be set to 1 to turn on the* SO_LINGER option, or set to 0 to turn off the SO_LINGER option.* `l_linger' indicates the amount of time to linger.  If `l_onoff' is* turned on and `l_linger' is set to 0, a default value TCP_LINGERTIME* (specified in netinet/tcp_timer.h) is used for incoming* connections accepted on the socket.* * When SO_LINGER is turned on and the `l_linger' field is set to 0,* TCP simply drops the connection by sending out an RST if a* connection is already established; frees up the space for the TCP* protocol control block; and wakes up all tasks sleeping on the* socket.* * For the client side socket, the value of `l_linger' is not changed* if it is set to 0.  To make sure that the value of `l_linger' is 0* on a newly accepted socket connection, issue another setsockopt()* after the accept() call.* * Currently the exact value of `l_linger' time is actually ignored* (other than checking for 0); that is, TCP performs the state* transitions if `l_linger' is not 0, but does not explicitly use its* value.* * .SS "TCP_NODELAY -- Delivering Messages Immediately"* Specify the TCP_NODELAY option for real-time protocols, such as the X* Window System Protocol, that require immediate delivery of many small* messages:* .CS*     setsockopt (sock, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof (optval));* .CE* The value at <optval> is an integer (type `int') set to either 1* (on) or 0 (off).* * By default, the VxWorks TCP implementation employs an algorithm that* attempts to avoid the congestion that can be produced by a large number* of small TCP segments. This typically arises with virtual terminal* applications (such as telnet or rlogin) across networks that have* low bandwidth and long delays.  The algorithm attempts to have no* more than one outstanding unacknowledged segment in the transmission* channel while queueing up the rest of the smaller segments for later* transmission.  Another segment is sent only if enough new data is* available to make up a maximum sized segment, or if the outstanding* data is acknowledged.* * This congestion-avoidance algorithm works well for virtual terminal* protocols and bulk data transfer protocols such as FTP without any* noticeable side effects.  However, real-time protocols that require* immediate delivery of many small messages, such as the X Window* System Protocol, need to defeat this facility to guarantee proper* responsiveness in their operation.* * TCP_NODELAY is a mechanism to turn off the use of this algorithm.* If this option is turned on and there is data to be sent out, TCP* bypasses the congestion-avoidance algorithm: any available data* segments are sent out if there is enough space in the send window.* * OPTION FOR DATAGRAM SOCKETS* The following section discusses an option for datagram (UDP) sockets.* * .SS "SO_BROADCAST -- Sending to Multiple Destinations"* Specify the SO_BROADCAST option when an application needs to send* data to more than one destination:* .CS

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -