tcp_echo.c
来自「在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LE」· C语言 代码 · 共 1,125 行 · 第 1/2 页
C
1,125 行
/*
* FILENAME: tcp_echo.c
*
* Copyright 2000 By InterNiche Technologies Inc. All rights reserved
*
* Test program for TCP sockets API. Implements an echo
* server and client
*
* MODULE: MISCLIB
*
* ROUTINES: tcp_client_add(), tcp_client_del(),
* ROUTINES: tcp_client_from_pio(), tcp_client_from_sock(), tcp_secho_init(),
* ROUTINES: tcp_secho_close(), tcp_cecho_close(), tcp_echo_cleanup(),
* ROUTINES: tcp_echo_init(), tcp_sendecho(), tcp_send_an_echo(),
* ROUTINES: echo_svr_upcall(), tcp_echo_recv(), tcp_echo_poll(),
* ROUTINES: tcp_echo_stats(),
*
* PORTABLE: yes
*/
#include "ipport.h" /* NetPort embedded system includes */
#ifdef TCP_ECHOTEST /* whole file can be ifdeffed out */
#ifndef WINSOCK
#include "tcpport.h" /* NetPort embedded system includes */
#include "in_utils.h"
/* define NP sockets to standard calls */
#define SOCKTYPE long
#define socket(x,y,z) t_socket(x,y,z)
#define bind(s,a,l) t_bind(s,a)
#define connect(s,a,l) t_connect(s,a)
#define listen(s,i) t_listen(s,i)
#define accept(s,a,l) t_accept(s,a)
#define send(s,b,l,f) t_send(s,b,l,f)
#define recv(s,b,l,f) t_recv(s,b,l,f)
#define socketclose(s) t_socketclose(s)
#define setsockopt(s, l, o, d) t_setsockopt(s, o, d)
#ifndef sock_noblock
#define sock_noblock(sock, flag) setsockopt(sock, SOL_SOCKET, SO_NBIO, NULL)
#endif
#endif /* WINSUCK */
#define ECHO_PORT 7 /* standard UDP/TCP echo port */
/* The states of a TCP_ECHO Client. Either it is IDLE or BUSY exchaning
TCP Echo packets */
#define TCP_IDLE 1
#define TCP_BUSY 2
/* TCP_IDLE_TIMEOUT is used to cleanup idle TCP Echo Client connections
If a TCP Echo Client has not been used for this long, delete it */
#define TCP_IDLE_TIMEOUT 600 /* value in seconds */
/* TCP_MAX_ECHO_CONN defines the maximum simultaneous TCP Echo
* Clients connections allowed. This is required because for polling
* TCP Echo Clients we are using t_select() call. t_select() uses
* fd_set array, which can hold a maximum of FD_SETSIZE sockets. As
* one socket is needed to poll TCP Echo Server, the maximum
* available for TCP Echo Clients is
*/
#define TCP_MAX_ECHO_CONN FD_SETSIZE-1 /* max TCP Echo Client conns*/
SOCKTYPE elisten_sock = INVALID_SOCKET; /* echo server socket */
SOCKTYPE esvr_sock = INVALID_SOCKET; /* echo server active socket */
extern int kbhit(void); /* from Microsquash|Borland lib*/
extern char * prompt;
/* This global switch can be set prior to calling tcp_echos_init() */
int tcpecho_server = TRUE;
/* Do we need to close the server's active socket? */
int esvr_sock_close = FALSE;
#ifndef ECHOBUFSIZE
#define ECHOBUFSIZE (8*1024)
#endif
/* List of error codes used by this file */
#define TCPE_BASE 400
#define TCPE_ALLOC_ERROR (TCPE_BASE+1)
#define TCPE_NODE_NOT_FOUND (TCPE_BASE+2)
#define TCPE_CANT_OPEN_SOCKET (TCPE_BASE+3)
#define TCPE_CONNECT_FAILED (TCPE_BASE+4)
#define TCPE_SEND_FAILED (TCPE_BASE+5)
#define TCPE_BAD_SOCKET (TCPE_BASE+6)
#define TCPE_BIND_FAILED (TCPE_BASE+7)
#define TCPE_LISTEN_FAILED (TCPE_BASE+8)
#define TCPE_CLIENT_NOT_FOUND (TCPE_BASE+9)
#define TCPE_TIME_NOT_RIPE (TCPE_BASE+10)
#define TCPE_ALL_SOCKS_USED (TCPE_BASE+11)
#define TCPE_BLOCKED (TCPE_BASE+12)
#define SUCCESS 0
/* Structure for holding information regarding a TCP Client connection */
struct TcpClient
{
SOCKTYPE sock; /* client socket */
void * pio; /* Output messages go to this device */
ip_addr rhost; /* TCP Echos to be sent to this host */
u_long replies; /* Number of burst replies received */
u_long times; /* Number of bursts is to be sent */
u_long send_cnt ; /* Number of the reply to be sent(counter) */
int state; /* state of the TCP connection */
u_long ticks; /* ClockTick when next burst is to be sent */
u_long delay; /* Delay between two Echo bursts */
u_long len; /* Length of TCP each burst to be sent */
u_long tot_sent; /* Total echo bytes sent */
u_long tot_rcvd; /* Total echo bytes received */
struct TcpClient * next;
char inbuf[ECHOBUFSIZE]; /* per-client data buffer */
int sending; /* non-zero while client is in send loop */
};
char * srv_inbuf = NULL;
typedef struct TcpClient * TCPCLIENT ;
TCPCLIENT tcpq; /* Start node for queue of TCP clients */
int tcp_client_add(void * pio);
int tcp_client_del(TCPCLIENT tcpclient);
TCPCLIENT tcp_client_from_pio (void * pio);
TCPCLIENT tcp_client_from_sock(SOCKTYPE sock);
int tcp_secho_init (void * pio);
int tcp_secho_close(void * pio);
int tcp_cecho_close(void * pio);
int tcp_send_an_echo(TCPCLIENT tcpclient);
void tcp_echo_poll(void);
int tcp_echo_init(void);
void tcp_echo_cleanup(void);
int tcp_echo_stats(void * pio);
int tcp_sendecho(void * pio, ip_addr fhost, long len, long times);
/* FUNCTION: tcp_client_add()
*
* Add a new client to the Queue
* 1. Allocates memory for a new node
* 2. Adds to queue
* 3. Initialized data members
*
*
* PARAM1: void * pio - device for console output
*
* RETURNS: 0 on SUCCESS or error number
*/
int
tcp_client_add(void * pio)
{
TCPCLIENT tmpclient;
int num_of_conn=0;
tmpclient=tcpq;
while ( tmpclient )
{
num_of_conn++;
tmpclient=tmpclient->next;
}
if ( num_of_conn >= TCP_MAX_ECHO_CONN )
{
return TCPE_ALL_SOCKS_USED ;
}
/* Allocate memory */
tmpclient = (TCPCLIENT) npalloc( sizeof(struct TcpClient) ) ;
if ( tmpclient == NULL )
{
ns_printf(pio,"Allocation error.\n");
return TCPE_ALLOC_ERROR;
}
/* Add the new node to the queue */
if ( tcpq == NULL )
{
tcpq = tmpclient ;
tmpclient->next=NULL;
}
else
{
/* Insert it at the beginning */
tmpclient->next = tcpq;
tcpq=tmpclient ;
}
/* Initialize data members */
tmpclient->sock = INVALID_SOCKET;
tmpclient->pio = pio;
tmpclient->rhost = 0;
tmpclient->times = 1; /* Count of total EchoPkts to be sent */
tmpclient->send_cnt = 0; /* Num of Echo Pkts sent till now */
tmpclient->ticks = cticks; /* Timetick to track sending of echos */
tmpclient->state = TCP_IDLE ; /* Are we sending TCP Echos? No. */
tmpclient->replies = 0 ; /* Num of replies received so far */
tmpclient->len = 64 ; /* Default value of Echo Pkt */
tmpclient->tot_sent = 0;
tmpclient->tot_rcvd = 0;
return SUCCESS ;
}
/* FUNCTION: tcp_client_del()
*
* Cleanup stuff for a TCP Echo Client Three things to be done here
* 1. Close the underlying socket
* 2. Remove node from the Q
* 3. Free the memory used by the node
*
* PARAM1: TCPCLIENT tcpclient - Pointer to TCP Echo Client connection
*
* RETURNS: 0 on SUCCESS or error number
*/
int
tcp_client_del(TCPCLIENT tcpclient)
{
int e;
TCPCLIENT tmpclient,prevclient;
/* Close the underlying socket */
if ( tcpclient->sock != INVALID_SOCKET )
{
e = socketclose(tcpclient->sock);
if (e)
{
e = t_errno(tcpclient->sock);
ns_printf(tcpclient->pio,"tcp echo: close error %d\n", e);
}
}
/* Remove from the q */
if ( tcpq == tcpclient )
{
/* It is the first node */
tcpq = tcpq->next;
}
else
{
prevclient=tcpq;
tmpclient=tcpq->next;
while ( tmpclient )
{
if ( tmpclient == tcpclient )
{
/* Found the node in the list */
prevclient->next=tmpclient->next ;
break;
}
else
{
prevclient=tmpclient;
tmpclient=tmpclient->next ;
}
}
/* Was the node found in Q ? */
if (tmpclient == NULL )
{
/* Node not found in Q !! */
dtrap("tcp_echo 0\n");
return TCPE_NODE_NOT_FOUND ;
}
}
npfree(tcpclient);
return SUCCESS;
}
/* FUNCTION: tcp_client_from_pio()
*
* Return the TCP Echo Client connect for a particular session.
*
* PARAM1: void * pio - device for console output
*
* RETURNS: Pointer to TCPCLIENT. NULL if connection not found.
*/
TCPCLIENT
tcp_client_from_pio(void * pio)
{
TCPCLIENT tmpclient=tcpq;
while ( tmpclient )
{
if ( tmpclient->pio == pio )
break ;
else
tmpclient=tmpclient->next;
}
return tmpclient;
}
/* FUNCTION: tcp_client_from_sock()
*
* Return the TCP Echo Client connection for a particular session.
*
* PARAM1: SOCKTYPE sock
*
* RETURNS: Pointer to TCPCLIENT. NULL if connection not found.
*/
TCPCLIENT
tcp_client_from_sock(SOCKTYPE sock)
{
TCPCLIENT tmpclient=tcpq;
while ( tmpclient )
{
if ( tmpclient->sock == sock )
break ;
else
tmpclient=tmpclient->next;
}
return tmpclient;
}
/* FUNCTION: tcp_secho_init()
*
* Initialize the TCP Echo Server. If the flag tcpecho_server is false,
* then Server Init is not done.
*
* PARAM1: void * pio - device for console output
*
* RETURNS: 0 on SUCCESS or error number.
*/
int
tcp_secho_init(void * pio)
{
int e; /* error holder */
struct sockaddr_in me; /* my IP info, for bind() */
int opt;
if (tcpecho_server)
{
ns_printf(pio,"tcp echo srv - starting.\n");
/* open TCP socket */
elisten_sock = socket(AF_INET, SOCK_STREAM, 0);
if (elisten_sock == INVALID_SOCKET)
{
ns_printf(pio,"TCP echo: bad socket: %d\n", elisten_sock);
return TCPE_BAD_SOCKET ;
}
opt = 1;
e = t_setsockopt(elisten_sock, SO_REUSEADDR, &opt);
if (e != 0)
{
e = t_errno(elisten_sock);
dtrap("tcp_echo 1\n");
dprintf("error %d setting SO_REUSEADDR on port %d\n", e, ECHO_PORT);
return SYS_SOCKETNULL;
}
me.sin_family = AF_INET;
me.sin_addr.s_addr = INADDR_ANY;
me.sin_port = htons(ECHO_PORT);
e = bind(elisten_sock, (struct sockaddr*)&me, sizeof(me));
if (e != 0)
{
e = t_errno(elisten_sock);
ns_printf(pio,"tcp_echo: bad socket bind: %d, %s\n", e, so_perror(e) );
socketclose(elisten_sock);
elisten_sock = INVALID_SOCKET;
return TCPE_BIND_FAILED ;
}
e = listen(elisten_sock, 3);
if (e != 0)
{
e = t_errno(elisten_sock);
ns_printf(pio,"tcp_echo: bad socket listen: %d %s\n", e, so_perror(e));
socketclose(elisten_sock);
elisten_sock = INVALID_SOCKET;
return TCPE_LISTEN_FAILED;
}
/* for listen socket into Non-blocking mode so we can poll accept */
sock_noblock(elisten_sock, TRUE);
}
else
ns_printf(pio,"tcp echo server not enabled\n");
srv_inbuf = (char *)npalloc(ECHOBUFSIZE);
if (srv_inbuf == NULL)
{
ns_printf(pio, "tcp server: alloc failed\n");
socketclose(elisten_sock);
elisten_sock = INVALID_SOCKET;
return TCPE_LISTEN_FAILED;
}
return SUCCESS;
}
/* FUNCTION: tcp_secho_close()
*
* Close the TCP Echo Server.
*
* PARAM1: void * pio - device for console output
*
* RETURNS: 0 on SUCCESS or error number.
*/
int
tcp_secho_close(void * pio)
{
int e = 0; /* scratch error holder */
int retval = 0; /* return last non-zero error */
if (esvr_sock != INVALID_SOCKET)
{
e = socketclose(esvr_sock);
if (e)
{
retval = e = t_errno(esvr_sock);
ns_printf(pio,"tcp echo server: close error %d %s\n", e, so_perror(e));
}
else
{
ns_printf(pio,"tcp echo srv - closing.\n");
esvr_sock = INVALID_SOCKET;
}
}
if (srv_inbuf)
{
npfree(srv_inbuf);
srv_inbuf=NULL;
}
if (elisten_sock == INVALID_SOCKET)
return e;
e = socketclose(elisten_sock);
if (e)
{
retval = e = t_errno(elisten_sock);
ns_printf(pio,"tcp echo: server close error %d %s\n", e, so_perror(e) );
}
elisten_sock = INVALID_SOCKET;
return retval;
}
/* FUNCTION: tcp_cecho_close()
*
* Close the TCP Echo Client.
*
* PARAM1: void * pio - device for console output
*
* RETURNS: 0 on SUCCESS or error number.
*/
int
tcp_cecho_close(void * pio)
{
TCPCLIENT tcpclient;
tcpclient=tcp_client_from_pio(pio);
if ( tcpclient == NULL )
{
ns_printf(pio,"No TCP Echo Client found for this session.\n");
return TCPE_CLIENT_NOT_FOUND ;
}
else
{
ns_printf(pio,"Closing TCP Echo Client.\n");
return tcp_client_del(tcpclient);
}
}
/* FUNCTION: tcp_echo_cleanup()
*
* Cleanup all TCP Echo related data structures.
*
* PARAM1: void
*
* RETURNS:
*/
void
tcp_echo_cleanup(void)
{
TCPCLIENT tcpclient=tcpq;
TCPCLIENT nextclient;
/* Close all the open clients */
while ( tcpclient )
{
nextclient=tcpclient->next;
tcp_client_del(tcpclient);
tcpclient=nextclient;
}
tcp_secho_close(NULL);
}
/* FUNCTION: tcp_echo_init()
*
* Initialize TCP Echo Server
* Remarks : This function has been defined so that a clean interface
* is provided for TCP Echo.
*
* PARAM1: void * pio - device for console output
*
* RETURNS: 0 on SUCCESS or error number.
*/
int
tcp_echo_init(void)
{
return tcp_secho_init(NULL);
}
/* FUNCTION: tcp_sendecho()
*
* Send TCP Echo packets to a TCP Echo Server. If a TCP Echo Client
* has not be created, then it is done (one per GenericIO device).
* Also, if the TCP Echo Server IP address is different from the
* one being used earlier, then socket reinitialization is done.
*
* PARAM1: void * pio - device for console output
* PARAM2: ip_addr fhost - IP Address of TCP Echo Server (IN)
* PARAM3: long len - Length of TCP Echo pkt to be sent (IN)
* PARAM4: long times) - Number of TCP Echo pkts to be sent (IN)
*
* RETURNS: 0 on SUCCESS or error number.
*/
int
tcp_sendecho(void * pio,
ip_addr fhost, /* already in net endian */
long len,
long times)
{
struct sockaddr_in sa;
int e;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?