tcpserv.c

来自「基于nucleus操作系统的GPRS无线数据传输终端全套源文件。包括支持ARM7」· C语言 代码 · 共 386 行

C
386
字号
/*************************************************************************/
/*                                                                       */
/*        Copyright (c) 1999 Accelerated Technology, Inc.		 */
/*                                                                       */
/* PROPRIETARY RIGHTS of Accelerated Technology are involved in the      */
/* subject matter of this material.  All manufacturing, reproduction,    */
/* use, and sales rights pertaining to this subject matter are governed  */
/* by the license agreement.  The recipient of this software implicitly  */
/* accepts the terms of the license.                                     */
/*                                                                       */
/*************************************************************************/

/*****************************************************************************/
/*                                                                           */
/* FILE NAME                                                                 */
/*                                                                           */
/*      TCPSERV.C                                                            */
/*                                                                           */
/*                                                                           */
/* DESCRIPTION                                                               */
/*                                                                           */
/*      This is a simple example of a TCP server.  It is an echo server,     */
/*      that is, any data received is echoed back to the client.  This       */
/*      program demonstrates the use of Nucleus NET over a PPP connection    */
/*                                                                           */
/*****************************************************************************/
#include <string.h>

#include "net\inc\externs.h"
#include "net\inc\socketd.h"
#include "net\inc\tcpdefs.h"
#include "plus\nucleus.h"

#include "ppp\inc\ppp.h"        /* PPP interface */

/* This is the IP address that will be assigned to a client during PPP
   negotiaton. */
UINT8   client_ip_address[] =  {192, 106, 34, 25};

/* This is the IP address the server will use. */
UINT8   server_ip_address[] =  {192, 106, 34, 50};

/* Define Application data structures.  */

NU_MEMORY_POOL    System_Memory;
NU_TASK           tcp_server_task_ptr;
NU_TASK           StrEcho0;
NU_TASK           StrEcho1;
NU_TASK           Control_Task;
NU_QUEUE          socketQueue;
NU_DEVICE         devices[1];

/* Define prototypes for function references.  */

VOID    tcp_server_task(UNSIGNED argc, VOID *argv);
VOID    str_echo(UNSIGNED argc, VOID *argv);
VOID    Controller(UNSIGNED argc, VOID *argv);
VOID    Error_Loop (INT error_num);

#define ECHO_LENGTH 1500
CHAR    line[ECHO_LENGTH + 1];

/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      Application_Initialize                                           */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      Application_Initialize performs any tasks that must be done      */
/*      before the first task executes.                                  */
/*                                                                       */
/*************************************************************************/
void    Application_Initialize(void *first_available_memory)
{

    VOID           *pointer;
    STATUS         status;
    
	/* Create a system memory pool that will be used to allocate task stacks,
       queue areas, etc.  */
    status = NU_Create_Memory_Pool(&System_Memory, "SYSMEM",
                        first_available_memory, 270000, 50, NU_FIFO);

    if (status != NU_SUCCESS)
    {
        Error_Loop (1);
    }


    /* Allocate stack space for and create each task in the system.  */
    
    /* Create tcp_server_task.  */
    status = NU_Allocate_Memory(&System_Memory, &pointer, 2000, NU_NO_SUSPEND);
    if (status != NU_SUCCESS)
    {
        Error_Loop (2);
    }
            
    /* Create the Application tasks. */
    status = NU_Create_Task(&tcp_server_task_ptr, "TCPSERV", tcp_server_task,
                        0, NU_NULL, pointer, 2000, 3, 0, NU_PREEMPT, NU_START);
    if (status != NU_SUCCESS)
    {
        Error_Loop (3);
    }
        

    status = NU_Allocate_Memory(&System_Memory, &pointer, 2000, NU_NO_SUSPEND);
    if (status != NU_SUCCESS)
    {
        Error_Loop (4);
    }
    	
    status = NU_Create_Task(&StrEcho0, "strecho", str_echo, 0, NU_NULL,
                pointer, 2000, 3, 0, NU_PREEMPT, NU_START);
    if (status != NU_SUCCESS)
    {
        Error_Loop (5);
    }

    status = NU_Allocate_Memory(&System_Memory, &pointer, 2000, NU_NO_SUSPEND);
    if (status != NU_SUCCESS)
    {
        Error_Loop (6);
    }
    	
    status = NU_Create_Task(&StrEcho1, "strecho", str_echo, 0, NU_NULL,
                pointer, 2000, 3, 0, NU_PREEMPT, NU_START);
    if (status != NU_SUCCESS)
    {
        Error_Loop (7);
    }

    status = NU_Allocate_Memory(&System_Memory, &pointer, 20000, NU_NO_SUSPEND);
    if (status != NU_SUCCESS)
    {
        Error_Loop (8);
    }
    
    status = NU_Create_Task(&Control_Task, "control", Controller, 0, NU_NULL,
                pointer, 2000, 10, 0, NU_PREEMPT, NU_START);
    if (status != NU_SUCCESS)
    {
        Error_Loop (9);
    }

    status = NU_Create_Queue(&socketQueue, "SocQueue", pointer, 10, NU_FIXED_SIZE,
                             1, NU_FIFO);
    if (status != NU_SUCCESS)
    {
        Error_Loop (10);
    }
    
   			
}   /* end Application_Initialize */

/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      tcp_server_task                                                  */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This is the task entry function for the task that will accept    */
/*      connection requests from clients.  Whenever a new connection is  */
/*      accepted the socket descriptor is pushed onto the Socket         */
/*      Descriptor queue.  The echo task will perform the actual         */
/*      communication with the client.                                   */
/*                                                                       */
/*************************************************************************/
VOID    tcp_server_task(UNSIGNED argc, VOID *argv)
{
    INT                 socketd, newsock;       /* the socket descriptor */
    struct addr_struct  servaddr;               /* holds the server address structure */
    STATUS              status;
    struct addr_struct  client_addr;
    UINT8               null_ip []    = {0, 0, 0, 0};   /* not used by PPP */
    CHAR                subnet_mask[] = {255, 255, 255, 0};


    /*  Remove warnings for unused parameters.  */
    status = (STATUS) argc + (STATUS) argv;


    if(NU_Init_Net(&System_Memory))  /* call network initialization */
    {
        Error_Loop (11);
    }

    memcpy (devices[0].dv_ip_addr, null_ip, 4);
    memcpy (devices[0].dv_subnet_mask, subnet_mask, 4);
    devices[0].dv_name = "PPP_Link";
    devices[0].dv_init = PPP_Initialize;
    devices[0].dv_flags = (DV_POINTTOPOINT | DV_NOARP);
    
    devices[0].dv_hw.uart.com_port         = COM2;
    devices[0].dv_hw.uart.baud_rate        = 38400;
    devices[0].dv_hw.uart.parity           = PARITY_NONE;
    devices[0].dv_hw.uart.stop_bits        = STOP_BITS_1;
    devices[0].dv_hw.uart.data_bits        = DATA_BITS_8;

    DEV_Init_Devices(devices, 1);

	/* Create the socket on which the server will listen for client
	   connections.
	*/
	if ((socketd = NU_Socket(NU_FAMILY_IP, NU_TYPE_STREAM, 0)) >=0 )
	{
		/* Fill in a structure with the server address. */
		servaddr.family    = NU_FAMILY_IP;
		servaddr.port	   = 7;
        *((UINT32 *)servaddr.id.is_ip_addrs) = IP_ADDR_ANY;

		/* make an NU_Bind() call to bind the server's address */
		if ((NU_Bind(socketd, &servaddr, 0))>=0)
		{
			/* be ready to accept connection requests */
			status = NU_Listen(socketd, 10);

			if (status == NU_SUCCESS)
			{
                /* Loop forever, accepting connections. Note that a max of
                   two concurrent echo tasks are allowed. */
				while (1)
				{
                    /* Accept a connection.  This service blocks by default until
                       a client has connected.
                    */
                    newsock = NU_Accept(socketd, &client_addr, 0);

                    /* If a client has connected then send the socket descriptor
                       to one of the echo tasks. */
                    if (newsock >= 0)
                    {
                        /* process the new connection */
                        status = NU_Send_To_Queue(&socketQueue,
                                                    (UNSIGNED *)&newsock,
                                                    1, NU_SUSPEND);
                        NU_Sleep(2);

                    } /* end successful NU_Accept */

				} /* while */

			} /* end successful NU_Listen */
		} /* end successful NU_Bind */

	} /* end successful NU_Socket */

}


/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*		Controller						 */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*	   This function waits for a caller. When a connection is made it*/
/*  waits until the connection is lost and then waits for another        */
/*  caller.                                                              */
/*                                                                       */
/*************************************************************************/

VOID Controller (UNSIGNED argc, VOID *argv)
{

	/* Modem Initialization string. */
    NU_Modem_Control_String("ATm0S0=0V1X4&K0^M", devices[0].dv_name);

    NU_Set_PPP_Client_IP_Address (client_ip_address, devices[0].dv_name);

    while (NU_TRUE)
	{
		/* Wait for slow modem */
        NU_Sleep (2);

		/* Wait for a client to call. */
        NU_Wait_For_PPP_Client(server_ip_address, devices[0].dv_name);

		/* Wait until the session is ended before we go on */
        while (NU_PPP_Still_Connected(devices[0].dv_name))
			NU_Relinquish();
	}
}

/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      str_echo                                                         */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*     This function waits for the server task to send it a socket       */
/*     descriptor via a queue.  It then communicates over the socket     */
/*     with the client.  This task first waits for data from the client. */
/*     It then echos the received data back to the client.               */
/*                                                                       */
/*************************************************************************/
VOID    str_echo(UNSIGNED argc, VOID *argv)
{
    int       connected;
    int       bytes_recv, bytes_sent;
    int       sockfd;
    STATUS    status;
    UNSIGNED  actSize;

    /*  Remove compilation warnings for unused parameters.  */
    status = (STATUS) argc + (STATUS) argv;

    /* Process echo requests forever. */
    while (NU_TRUE)
    {
        connected = NU_TRUE;

        status = NU_Receive_From_Queue(&socketQueue, (UNSIGNED *) &sockfd, 1,
                                      &actSize, NU_SUSPEND);
        if (status != NU_SUCCESS)
            NU_Suspend_Task (NU_Current_Task_Pointer());

        /* Turn on the "block during a read" flag.  NU_Receive is non-blocking by
           default.  This will cause the receive call to block until data is
           received.
        */
        NU_Fcntl(sockfd, NU_SETFLAG, NU_BLOCK);

        while(connected)
        {
             /* Receive some data. */
             bytes_recv = NU_Recv(sockfd, line, ECHO_LENGTH, 0);

             /* Check to see if the client closed his end of the connection.  If so
                then we need to close this end as well. */
             if (bytes_recv == NU_NOT_CONNECTED)
             {
                 connected = NU_FALSE;
                 continue;
             }
             else if (bytes_recv < 0)
             {
                 connected = NU_FALSE;
                 continue;
             }
             else
             {
                line[bytes_recv] = 0x0;

                /* Echo the data back to the client. */
                bytes_sent = NU_Send(sockfd, line, bytes_recv, 0);

                if(bytes_sent != bytes_recv)
                {
                    connected = NU_FALSE;
                    continue;
                }
            }
        }

        /* close the connection */
        if ((NU_Close_Socket(sockfd)) != NU_SUCCESS)
        {
            Error_Loop (12);
        }

    } /* while */

}

VOID Error_Loop (INT error_num)
{
    INT x, y;

    while (NU_TRUE)
    {
        x++;
        y++;
    }
}

⌨️ 快捷键说明

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