recv.c
来自「用于嵌入式系统的TCP/IP协议栈」· C语言 代码 · 共 501 行 · 第 1/2 页
C
501 行
return -1; } /*-------------------------------------------------------------------*/ /* Check destination buffer address and flag parameters. */ /*-------------------------------------------------------------------*/ if ((dst == NULL) || ((flags & MSG_DONTWAIT) && (flags & MSG_WAITALL))) { NetError(sock, EFAULT); return -1; }#endif /*-------------------------------------------------------------------*/ /* Return success if requested data length is zero. */ /*-------------------------------------------------------------------*/ if (wanted == 0) return 0; /*-------------------------------------------------------------------*/ /* Gain exclusive socket API access and stack internals access. */ /*-------------------------------------------------------------------*/ if (semPend(sock->api_access, WAIT_FOREVER)) { NetError(NULL, ENOTSOCK); return -1; } semPend(Net.IntSem, WAIT_FOREVER); /*-------------------------------------------------------------------*/ /* Check if socket has been shutdown for receives. */ /*-------------------------------------------------------------------*/ if (sock->flags & SF_RCV_SHUT) { NetError(sock, ESHUTDOWN); goto recv_exit; } /*-------------------------------------------------------------------*/ /* UDP socket read. */ /*-------------------------------------------------------------------*/ if (sock->type == SOCK_DGRAM) { NetBuf *buf; int datalen; /*-----------------------------------------------------------------*/ /* Check for illegal flag options. */ /*-----------------------------------------------------------------*/ if (flags & (MSG_OOB | MSG_WAITALL)) { NetError(sock, EOPNOTSUPP); goto recv_exit; } /*-----------------------------------------------------------------*/ /* If from not NULL, verify fromlen is valid. */ /*-----------------------------------------------------------------*/ if (from && (*fromlen != sizeof(struct sockaddr_in))) { NetError(sock, EFAULT); goto recv_exit; } /*-----------------------------------------------------------------*/ /* Verify socket is bound. */ /*-----------------------------------------------------------------*/ if (sock->local.sin_port == 0) { NetError(sock, EINVAL); goto recv_exit; } /*-----------------------------------------------------------------*/ /* Check if no receive buffers are waiting. */ /*-----------------------------------------------------------------*/ if (sock->rq_head == NULL) { /*---------------------------------------------------------------*/ /* Return error if operation is non-blocking. */ /*---------------------------------------------------------------*/ if ((sock->flags & SF_NONBLKNG) || (flags & MSG_DONTWAIT)) { NetError(sock, EWOULDBLOCK); goto recv_exit; } /*---------------------------------------------------------------*/ /* Wait for "data received" event. */ /*---------------------------------------------------------------*/ NetPendEvent(sock, SE_DATA_RCVD, sock->recv_timeo); /*---------------------------------------------------------------*/ /* Check for timeout or error while we pended. */ /*---------------------------------------------------------------*/ if (sock->error) { NetError(sock, sock->error); goto recv_exit; } } /*-----------------------------------------------------------------*/ /* Copy data to application buffer. */ /*-----------------------------------------------------------------*/ buf = sock->rq_head; datalen = buf->app_len; rcvd = min(wanted, datalen); memcpy(dst, buf->app_data, rcvd); /*-----------------------------------------------------------------*/ /* Output datagram source address if requested. */ /*-----------------------------------------------------------------*/ if (from) { struct sockaddr_in addr; Ip *ip = (Ip *)buf->ip_pkt; Udp *udp = buf->ip_data; memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_port = udp->src_port; addr.sin_addr.s_addr = ip->src_ip; *(struct sockaddr_in *)from = addr; } /*-----------------------------------------------------------------*/ /* Unless just peeking, extract and recycle queued buffer. */ /*-----------------------------------------------------------------*/ if ((flags & MSG_PEEK) == FALSE) { sock->rq_head = buf->next; --sock->q_count; tcpRetBuf(&buf); } /*-----------------------------------------------------------------*/ /* Check whether datagram was truncated. */ /*-----------------------------------------------------------------*/ if (datalen > wanted) { NetError(sock, EMSGSIZE); rcvd = -1; goto recv_exit; } } /*-------------------------------------------------------------------*/ /* TCP socket read. */ /*-------------------------------------------------------------------*/ else { int len; /*-----------------------------------------------------------------*/ /* Check for illegal flag options. */ /*-----------------------------------------------------------------*/ if ((flags & MSG_PEEK) && (flags & MSG_WAITALL)) { NetError(sock, EOPNOTSUPP); goto recv_exit; } /*-----------------------------------------------------------------*/ /* Ensure urgent data is available if requested. */ /*-----------------------------------------------------------------*/ if ((flags & MSG_OOB) && !(sock->flags & SF_OOB_DATA)) { NetError(sock, EINVAL); goto recv_exit; } /*-----------------------------------------------------------------*/ /* Loop to read the requested number of bytes. */ /*-----------------------------------------------------------------*/ for (rcvd = 0; rcvd < wanted; dst = (char *)dst + len, rcvd += len) { /*---------------------------------------------------------------*/ /* Attempt to read data from TCP socket. */ /*---------------------------------------------------------------*/ len = tcp_recv(sock, dst, wanted - rcvd, flags); /*---------------------------------------------------------------*/ /* Break if FIN received. */ /*---------------------------------------------------------------*/ if (len == 0) break; /*---------------------------------------------------------------*/ /* Check if some data has been previously read. */ /*---------------------------------------------------------------*/ if (rcvd) { /*-------------------------------------------------------------*/ /* Break to normal exit if error occurred. */ /*-------------------------------------------------------------*/ if (len < 0) break; } /*---------------------------------------------------------------*/ /* Else this is first pass through loop. */ /*---------------------------------------------------------------*/ else { /*-------------------------------------------------------------*/ /* Go to error exit if error occurred. */ /*-------------------------------------------------------------*/ if (len < 0) { rcvd = -1; goto recv_exit; } /*-------------------------------------------------------------*/ /* Break if retries not requested. */ /*-------------------------------------------------------------*/ if ((flags & MSG_WAITALL) == 0) { rcvd = len; break; } } } } /*-------------------------------------------------------------------*/ /* Release exclusive API and internals access. Return status code. */ /*-------------------------------------------------------------------*/recv_exit: semPost(sock->api_access); semPost(Net.IntSem); return rcvd;}/***********************************************************************//* recv: Receive data from socket *//* *//* Inputs: s = socket identifier *//* dst = pointer to destination buffer *//* wanted = amount of data requested read *//* flags = option flags *//* *//***********************************************************************/int (recv)(int s, void *dst, int wanted, int flags){ return recvfrom(s, dst, wanted, flags, 0, 0);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?