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