udp_echo.c

来自「在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LE」· C语言 代码 · 共 760 行 · 第 1/2 页

C
760
字号
   me.sin_addr.s_addr = INADDR_ANY;
   me.sin_port = htons(ECHO_PORT);

   e = bind(sock, (struct sockaddr*)&me);
   if (e != 0)
   {
      e = t_errno(sock);
      ns_printf(pio,"udp_echo: bind error: %d\n", e);
      socketclose(sock);
      return UDPE_SRV_BIND_FAILED;
   }

   es_sock = sock;

   /* put socket into non-blocking mode */
   setsockopt(sock, SOL_SOCKET, SO_NBIO, NULL);

   return SUCCESS;
}


/* FUNCTION: udp_cecho_close()
 *
 * Close the UDP Echo Client for a particular session.
 * This function in turn calls udp_client_del().
 *
 * PARAM1: void * pio
 *
 * RETURNS: SUCCESS or error number 
 */

int
udp_cecho_close(void * pio)
{
   UDPCLIENT udpclient;

   udpclient=udp_client_from_pio(pio);
   if (udpclient == NULL )
   {
      ns_printf(pio,"echo socket not open\n");
      return UDPE_NO_CONN_FOUND;
   }

   ns_printf(pio,"udp echo - closing client socket\n");

   udp_client_del(udpclient);

   return SUCCESS;
}


/* FUNCTION: udp_secho_close()
 *
 * Cleanup the UDP Echo Server
 *
 * PARAM1: void * pio
 *
 * RETURNS: SUCCESS or error number 
 */

int
udp_secho_close(void * pio)
{
   int   e=0;
   SOCKTYPE sock;

   sock = es_sock;
   es_sock = INVALID_SOCKET;

   if ( sock != INVALID_SOCKET )
   {
      ns_printf(pio,"udp echo - closing server socket\n");
      e = socketclose(sock);
      if (e)
      {
         e = t_errno(sock);
         ns_printf(pio,"udp echo: close error %d\n", e);
      }
   }

   if ( e )
      return UDPE_SRV_CLOSE_ERR ;
   else
      return SUCCESS ;
}


/* FUNCTION: udp_sendecho()
 *
 * Send UDP Echo packets to a remote host. When a UDP Echo Client is 
 * initialized for a session, rhost field is set to the global 
 * variable activehost. If this function is called for a different 
 * rhost, then 1. The previous client connection is closed. 2. A new 
 * client connection is started for this new rhost.
 *
 * PARAM1: void * pio
 * PARAM2: ip_addr rhost   - IP Address of remote host
 * PARAM3: int len         - Length of packet to be sent
 * PARAM4: long times      - Number of times packet is to be sent
 *
 * RETURNS: SUCCESS or error number 
 */

int
udp_sendecho(void * pio,
   ip_addr rhost,    /* already in net endian */
   int   len,        /* length to send */
   long  times)      /* packet length, number of times to send */
{
   int   e;
   UDPCLIENT udpclient;

   udpclient=udp_client_from_pio(pio);

   if (udpclient == NULL || rhost != udpclient->rhost)
   {
      if ( udpclient == NULL )
      {
         ns_printf(pio,"echo socket not open. Opening....\n");
      }
      else
      {
         ns_printf(pio,"host changed, restarting client socket \n");
         udp_client_del(udpclient);
      }

      activehost = rhost;
      e = udp_cecho_init(pio);
      if (e) 
         return e;

      udpclient=udp_client_from_pio(pio);
   }

   udpclient->replies   = 0;
   udpclient->times     = times;
   udpclient->delay     = pingdelay;
   udpclient->ticks     = cticks;
   udpclient->state     = UDP_BUSY ;
   udpclient->len       = len ;
   udpclient->send_cnt  = 0 ;

   return udp_send_an_echo(udpclient);
}


/* FUNCTION: udp_send_an_echo()
 *
 * Send an Echo packet for a UDP Echo Client.
 *
 * PARAM1: UDPCLIENT udpclient
 *
 * RETURNS: 0 if SUCCESS or error number
 */

int
udp_send_an_echo(UDPCLIENT udpclient)
{
   int   e;

   if ( udpclient->ticks > cticks )  
      return UDPE_TIME_NOT_RIPE ;

   udpclient->ticks += udpclient->delay;  /* Set time for sending next packet*/

   ns_printf(udpclient->pio,"sending UDP echo %ld to %s\n",
    udpclient->send_cnt,print_ipad(udpclient->rhost));

   sprintf_t(echodata + 17, "%-9lu", udpclient->send_cnt );
   e = t_send(udpclient->sock, echodata, udpclient->len, 0);
   if (e != udpclient->len)
   {
      e = t_errno(udpclient->sock);
      ns_printf(udpclient->pio,"error %d sending UDP echo number %ld\n", e, 
       udpclient->send_cnt );
      ns_printf(udpclient->pio,"UDP Echo Server at %s is possibly shut down\n",
         print_ipad(udpclient->rhost));
      udp_client_del(udpclient);
      return UDPE_ERR_SENDING_ECHO ;
   }

   udpclient->send_cnt ++;
   udpclient->tot_sent ++;

   return SUCCESS;
}


/* FUNCTION: udp_echo_poll()
 * 
 * Poll all the UDP Echo related activities. That includes a UDP
 * Echo Server and UDP Echo Clients for each I/O session.
 *
 * PARAM1: 
 *
 * RETURNS: void
 */

static char inbuf[TCP_MSS];

void
udp_echo_poll()
{
   struct sockaddr_in   him;  /* IP info of current rhost */
   int   len;
   int   e;
   UDPCLIENT tmpclient,nextclient;

   in_udpechoq++;    /* don't re-entry from tk_yield() */
   if (in_udpechoq != 1)
   {
      in_udpechoq--;
      return;
   }

   /* check for received echo packet */
   if (es_sock != INVALID_SOCKET)
   {
      len = recvfrom(es_sock, inbuf, TCP_MSS, 0, (struct sockaddr *)&him);
      if (len < 0)
      {
         e = t_errno(es_sock);
         if (e != EWOULDBLOCK)
            dprintf("UDP echo server socket error %d\n", e);
      }
      else if(len == 0)
      {
         dtrap("tcp_echo 1\n"); /* socket closed? */
         udp_secho_close(NULL);
      }
      else  /* if(len > 0) */
         sendto(es_sock, inbuf, len, 0, (struct sockaddr *)&him);
   }

   for (tmpclient = udpq; tmpclient; tmpclient = nextclient)
   {
      nextclient=tmpclient->next;

      /* check for received echo reply */
      len = t_recv(tmpclient->sock, inbuf, TCP_MSS, 0);
      if (len < 0)
      {
         e = t_errno(tmpclient->sock);
         if (e != EWOULDBLOCK)
            ns_printf(tmpclient->pio,"UDP echo client socket error %d\n", e);
      }
      else if(len == 0)
      {
         dtrap("tcp_echo 2\n"); /* socket closed? */
         tmpclient->sock=INVALID_SOCKET;
         udp_client_del(tmpclient);
         continue;
      }
      else  /* if(len > 0) - got some echo data */
      {
         ns_printf(tmpclient->pio,"UDP echo reply; len:%d, reply:%lu", 
          len, tmpclient->replies);
         tmpclient->replies++;
         tmpclient->tot_rcvd++;
         /* see if it's one of ours, print number if so */
         if (strncmp(inbuf, echodata, 16) == 0)
            ns_printf(tmpclient->pio,", Our send#:%ld",atol((&inbuf[17])));
         ns_printf(tmpclient->pio,"\n%s",prompt);
      }

      if ( tmpclient->state == UDP_BUSY )
      {
         if ( tmpclient->send_cnt  >= tmpclient->times )
         {
            /* Previous "udecho" command has completed */
            tmpclient->state = UDP_IDLE ;
         }
         else
         {
            if ( udp_send_an_echo(tmpclient) == SUCCESS )
               ns_printf(tmpclient->pio,"%s",prompt);
         }
      }
      if ( tmpclient->ticks + (UDP_IDLE_TIMEOUT*TPS) < cticks )
      {
         /* This client has been lying around ldle for a long time */
         ns_printf(tmpclient->pio,"Deleting idle UDP Echo Client.\n%s",prompt);
         udp_client_del(tmpclient);
      }
   }

   in_udpechoq--;
}



/* FUNCTION: udp_echo_init()
 * 
 * Do the initialization for UDP Echo - start UDP Echo Server
 *
 * PARAM1: void
 *
 * RETURNS: 0 on SUCCESS or error number 
 */

int
udp_echo_init(void)
{
   return udp_secho_init(NULL);
}



/* FUNCTION: udp_echo_cleanup()
 * 
 * Clean up UDP Echo Server and UDP Echo Clients.
 *
 * PARAM1: void
 *
 * RETURNS: 0 on SUCCESS or error number 
 */

void
udp_echo_cleanup(void)
{
   UDPCLIENT tmpclient=udpq;
   UDPCLIENT nextclient;

   /* Close the Echo Server sockets */
   udp_secho_close(NULL);

   /* Do the cleanup for each client connection */
   while ( tmpclient )
   {
      nextclient=tmpclient->next;
      udp_client_del(tmpclient);
      tmpclient=nextclient;
   }
}



/* FUNCTION: udp_echo_stats()
 * 
 *  Show statistics about all UDP Echo Clients and Servers
 *
 * PARAM1: void * pio
 *
 * RETURNS: 0 on SUCCESS or error number
 */

int
udp_echo_stats(void * pio)
{
   ns_printf(pio,"Showing UDP Echo statistics.\n");
   if ( es_sock == INVALID_SOCKET )
   {
      ns_printf(pio,"   There are no Server connections.\n");
   }
   else
   {
      ns_printf(pio,"   There is one Server connection.\n");
   }

   if ( udpq == NULL )
      ns_printf(pio,"   There are no Client connections.\n");
   else
   {
      UDPCLIENT tmpclient=udpq;
      int   cnt=0;
      while (tmpclient)
      {
         cnt++;
         ns_printf(pio,"   Total pkts for Client %d: sent=%ld,rcvd=%ld\n",
          cnt,tmpclient->tot_sent,tmpclient->tot_rcvd);
         tmpclient=tmpclient->next;
      }
      ns_printf(pio,"   Total Client connections=%d.\n",cnt);
   }
   return SUCCESS;
}

#endif      /* UDPSTEST */

⌨️ 快捷键说明

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