recv.c
来自「用于嵌入式系统的TCP/IP协议栈」· C语言 代码 · 共 501 行 · 第 1/2 页
C
501 行
/***********************************************************************//* *//* Module: recv.c *//* Release: 2001.3 *//* Version: 2001.0 *//* Purpose: recv() and recvfrom() implementation *//* *//*---------------------------------------------------------------------*//* *//* Copyright 2001, Blunk Microsystems *//* ALL RIGHTS RESERVED *//* *//* Licensees have the non-exclusive right to use, modify, or extract *//* this computer program for software development at a single site. *//* This program may be resold or disseminated in executable format *//* only. The source code may not be redistributed or resold. *//* *//***********************************************************************/#include "../tcp_ipp.h"#include "../tcp/tcp.h"#include "../ip/ip.h"#include <string.h>/***********************************************************************//* Local Function Definitions *//***********************************************************************//***********************************************************************//* tcp_recv: Receives data from TCP socket *//* *//* Inputs: sock = pointer to a TCP socket *//* ptr = pointer to destination buffer *//* len = amount of data requested *//* flags = behavior modifiers *//* *//* Returns: number received or -1 with errno set to error code *//* *//***********************************************************************/static int tcp_recv(SOCKET sock, ui8 *ptr, uint len, int flags){ NetBuf *buf; /*-------------------------------------------------------------------*/ /* Check if the receive buffer is empty. */ /*-------------------------------------------------------------------*/ if (sock->rb_count == 0) { /*-----------------------------------------------------------------*/ /* Return 0 if nothing more to receive. */ /*-----------------------------------------------------------------*/ if (sock->flags & SF_GOTFIN) return 0; /*-----------------------------------------------------------------*/ /* Verify that socket is connected. */ /*-----------------------------------------------------------------*/ if ((sock->flags & SF_CONNECTED) == FALSE) { if (sock->error == 0) sock->error = ENOTCONN; NetError(sock, sock->error); return -1; } /*-----------------------------------------------------------------*/ /* Else return error if operation is non-blocking. */ /*-----------------------------------------------------------------*/ else if ((sock->flags & SF_NONBLKNG) || (flags & MSG_DONTWAIT)) { NetError(sock, EWOULDBLOCK); return -1; } /*-----------------------------------------------------------------*/ /* Else wait for data. */ /*-----------------------------------------------------------------*/ else { /*---------------------------------------------------------------*/ /* Wait for "data received" or "got FIN" event. */ /*---------------------------------------------------------------*/ NetPendEvent(sock, SE_DATA_RCVD | SE_GOT_FIN, sock->recv_timeo); /*---------------------------------------------------------------*/ /* If still no data, either a FIN arrived or an error occurred. */ /*---------------------------------------------------------------*/ if (sock->rb_count == 0) { if (sock->flags & SF_GOTFIN) return 0; else { NetError(sock, sock->error); return -1; } } } } /*-------------------------------------------------------------------*/ /* Limit len to minimum of requested data and available data. */ /*-------------------------------------------------------------------*/ if (len > sock->rb_count) len = sock->rb_count; /*-------------------------------------------------------------------*/ /* Check if a receive buffer has been queued. */ /*-------------------------------------------------------------------*/ buf = sock->rq_head; if (buf) { struct tcp *tcp = (struct tcp *)buf->ip_data; /*-----------------------------------------------------------------*/ /* Check if we can read directly from the queued buffer. */ /*-----------------------------------------------------------------*/ if (tcp->seq_num == sock->rd_nxt) { int app_len = buf->app_len; /*---------------------------------------------------------------*/ /* Limit read to amount of data in queued receive buffer. */ /*---------------------------------------------------------------*/ if (len > app_len) len = app_len; memcpy(ptr, buf->app_data, len); } /*-----------------------------------------------------------------*/ /* Else limit len to amount already copied to socket buffer. */ /*-----------------------------------------------------------------*/ else { int copied = tcp->seq_num - sock->rd_nxt; if (len > copied) len = copied; buf = NULL; } } /*-------------------------------------------------------------------*/ /* If unable to read from queued buffer, read from socket buffer. */ /*-------------------------------------------------------------------*/ if (buf == NULL) { if ((sock->rb_start + len) <= sock->rb_size) { memcpy(ptr, &sock->rbuf[sock->rb_start], len); } else { int len1 = sock->rb_size - sock->rb_start; memcpy(ptr, &sock->rbuf[sock->rb_start], len1); memcpy(ptr + len1, &sock->rbuf[0], len - len1); } } /*-------------------------------------------------------------------*/ /* If not just peeking, account for data removed. */ /*-------------------------------------------------------------------*/ if ((flags & MSG_PEEK) == 0) { int actual; /*-----------------------------------------------------------------*/ /* Update buffer count, read sequence number, and data offset. */ /*-----------------------------------------------------------------*/ sock->rb_count -= len; sock->rd_nxt += len; sock->rb_start += len; if (sock->rb_start >= sock->rb_size) sock->rb_start -= sock->rb_size; /*-----------------------------------------------------------------*/ /* Free buffer if all read, else just trim data from beginning. */ /*-----------------------------------------------------------------*/ if (buf) { if (len == buf->app_len) { sock->rq_head = buf->next; buf->flush = NULL; TcpAssert(buf->seg_record == NULL); } else { TcpTrimBeg(buf, len); } } /*-----------------------------------------------------------------*/ /* Consider window update if window has opened by two segments. */ /*-----------------------------------------------------------------*/ actual = sock->rb_size - sock->rb_count; if (actual >= (sock->rcv_mss << 1) + sock->rcv_win) { /*---------------------------------------------------------------*/ /* If peer has not finished sending, send a window update. */ /*---------------------------------------------------------------*/ if ((sock->flags & SF_GOTFIN) == FALSE) { sock->flags |= SF_SENDFLG; TcpTryOut(sock); } } } return len;}/***********************************************************************//* Global Function Definitions *//***********************************************************************//***********************************************************************//* recvfrom: Receive data from socket *//* *//* Inputs: s = socket identifier *//* dst = pointer to destination buffer *//* wanted = amount of data requested read *//* flags = option flags *//* from = pointer to optional destination address *//* fromlen = pointer to sizeof(struct sockaddr_in) *//* *//* Returns: number received or -1 with errno set to error code *//* *//***********************************************************************/int recvfrom(int s, void *dst, int wanted, int flags, void *from, int *fromlen){ SOCKET sock = &Socks[s - 1]; int rcvd = -1;#if OS_PARM_CHECK /*-------------------------------------------------------------------*/ /* Verify protocol has been initialized. */ /*-------------------------------------------------------------------*/ if (!Net.Initialized) { NetError(NULL, ENETDOWN); return -1; } /*-------------------------------------------------------------------*/ /* Check for valid socket ID. */ /*-------------------------------------------------------------------*/ if (InvalidHandle(s)) { NetError(NULL, ENOTSOCK);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?