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 + -
显示快捷键?