/**********************************************************************
chengjy@felab, copyright 2002-2004
vxSvr.h
网络监控任务需要的常数,只定义相关常数,其它常数
需要编程用户自己定义。
**********************************************************************/
#ifndef _VXSVR_H
#define _VXSVR_H
/*服务器初始化情况*/
#define NET_INIT_LISTENSKT 0x01
#define NET_INIT_COMMUSKT 0x02
#define NET_INIT_NULL 0x00
/*定义网络关闭时是否要重新初始化*/
#define MODE_NET_DEFAULT 0 /*重新初始化*/
#define MODE_NET_REINIT 1 /*不再初始化*/
/*定义任务名*/
#define TNAME_NETINIT "tNetInit"
#define TNAME_NETRECV "tNetRecv"
#define TNAME_NETSEND "tNetSend"
#define TNAME_NETCHECKLINK "tNetCheckLink"
#define TNAME_NETCLOSEALL "tNetCloseAll"
/*用户任务堆栈大小*/
#define USER_STACK_SIZE 2000
/*taskSpawn使用的用户任务优先级*/
#define TPRI_NETCLOSEALL 101
#define TPRI_NETCHECKLINK 102
#define TPRI_NETRECV 103
#define TPRI_NETSEND 104
#define TPRI_NETINIT 105
#endif /*_VXSVR_H*/
/**********************************************************************
chengjy@felab, copyright 2002-2004
vxSvr.c
VxWorks下建立服务器端的程序框架,加上了网络监测的模块。
函数:
void netInit(int mode);
void netCMDRecv();
void netCMDSend();
void netCloseAll(int mode);
void netCheckLink();
调用: 无
被调用: shell下手动调用
说明: 编译下载完毕后,在shell下输入sp netInit
初始化服务器端即可。注意本文档仅仅是框架,用户还需要
根据需要添加内容。为了简洁起见,函数都设定为无返回。
**********************************************************************/
#include "vxWorks.h"
#include "taskLib.h"
#include "sockLib.h"
#include "inetLib.h"
#include "ioLib.h"
#include "logLib.h"
#include "string.h"
#include "stdio.h"
#include "netinet\\tcp.h"
#include "semLib.h"
#include "vxSvr.h"
int flagNetInit = NET_INIT_NULL; /*服务器初始化标志,程序中省略了对应的判断和操作*/
int listenSkt; /*侦听socket*/
int commuSkt; /*通讯socket*/
SEM_ID semCmdLink; /*网络连接出错信号灯*/
void netInit(int mode);
void netCMDRecv();
void netCMDSend();
void netCloseAll(int mode);
void netCheckLink();
/*此处需要extern 外部关于队列操作的函数和全局变量*/
/**********************************************************************
void netInit(int mode);
函数说明: 网络初始化程序
参数: mode, 分为MODE_NET_DEFAULT 和MODE_NET_REINIT 两种,
分别对应初始化侦听+通讯套接字和只
初始化通讯套接字两种。
返回: 无
调用:
void netCMDRecv();
void netCMDSend();
void netCheckLink();
被调用: 用户程序初始化模块
char netCloseAll(int mode);
**********************************************************************/
void netInit(int mode)
{
/*需要添加重入控制*/
if(mode == MODE_NET_DEFAULT)
{
/*建立本地的侦听用套接字listenSkt 并bind和listen*/
}
/*接收外部联接,建立通讯套接字commuSkt*/
if(1/*改成已经正确建立通讯套接字的判断*/)
{
/*初始化网络通讯的缓冲对列*/
/*初始化缓冲队列的信号灯*/
/*发起网络命令循环接收任务、命令发送任务和网络监控任务*/
taskDelete(taskNameToId(TNAME_NETCHECKLINK));
taskSpawn(TNAME_NETCHECKLINK,TPRI_NETCHECKLINK,0,USER_STACK_SIZE,
(FUNCPTR)netCheckLink,0,0,0,0,0,0,0,0,0,0);
taskDelete(taskNameToId(TNAME_NETRECV));
taskSpawn(TNAME_NETRECV,TPRI_NETRECV,0,USER_STACK_SIZE,
(FUNCPTR)netCMDRecv,0,0,0,0,0,0,0,0,0,0);
taskDelete(taskNameToId(TNAME_NETSEND));
taskSpawn(TNAME_NETSEND,TPRI_NETSEND,0,USER_STACK_SIZE,
(FUNCPTR)netCMDSend,0,0,0,0,0,0,0,0,0,0);
}
}
/**********************************************************************
void netCMDSend();
函数说明: 循环从网络发送缓冲队列中取出数据并发送
参数: 无
返回: 无
调用: 外部的队列处理函数
被调用: void netInit(int mode)
**********************************************************************/
void netCMDSend()
{
while(1)
{
/*从缓冲对列获取数据,此处使用信号灯同步,在
没有数据要发送时任务被阻塞,不会占用CPU*/
/*发送数据*/
if(send(commuSkt,0,0,0/*改成其它三个参数*/) == ERROR)
{
/*发送错误*/
logMsg("netSend: error in sending buff to client\n",0,0,0,0,0,0);
semGive(semCmdLink);
break;
}
}
}
/**********************************************************************
void netCMDRecv()
函数说明: 从已经建立的网络通道循环接收数据,并添加到接收
缓冲队列等待处理
参数: 无
返回: 无
调用: 外部的队列处理函数
被调用: STATUS netInit();
**********************************************************************/
void netCMDRecv()
{
int recvLen; /*实际接收数据的长度*/
while(1)
{
recvLen = recv(commuSkt,0,0,0/*改成其他三个参数*/);
if(recvLen!=ERROR && recvLen!=0)
{
/*添加到队列中等待处理*/
}
else
{
/*接收出错*/
logMsg("netCMDRecv: error in receive data from client\n",0,0,0,0,0,0);
semGive(semCmdLink);
break;
}
}
}
/**********************************************************************
void netCloseAll(int mode)
函数说明: 函数说明: 关闭侦听socket ,并删除命令缓冲
队列以及与socket相关的任务,并根据模式的
不同选择是直接关闭侦听套接字 (MODE_NET_DEFAULT)
还是重新初始化网络(MODE_NET_REINIT)
参数: mode, 选择关闭方式
返回: 无
调用: void netInit(int mode);
被调用: void netCheckLink();
用户在shell下调用
**********************************************************************/
void netCloseAll(int mode)
{
int taskId;
/*删除网络相关任务*/
taskId = taskNameToId(TNAME_NETRECV);
if(taskId!=taskIdSelf() && taskId!=ERROR)
{
taskDelete(taskId);
}
taskId = taskNameToId(TNAME_NETSEND);
if(taskId!=taskIdSelf() && taskId!=ERROR)
{
taskDelete(taskId);
}
taskId = taskNameToId(TNAME_NETCHECKLINK);
if(taskId!=taskIdSelf() && taskId!=ERROR)
{
taskDelete(taskId);
}
/*调用外部函数删除缓冲队列*/
/*删除缓冲队列的信号灯*/
/*删除网络通断检测用信号灯*/
semDelete(semCmdLink);
/*根据网络初始化的不同状态作相应的退出工作*/
if(mode==MODE_NET_DEFAULT)
{
close(commuSkt);
close(listenSkt);
}
else if(mode==MODE_NET_REINIT)
{
close(listenSkt);
/*重新初始化网络*/
taskDelete(taskNameToId(TNAME_NETINIT));
taskSpawn(TNAME_NETINIT,TPRI_NETINIT,0,USER_STACK_SIZE,
(FUNCPTR)netInit,mode,0,0,0,0,0,0,0,0,0);
}
}
/**********************************************************************
void netCheckLink()
函数说明: 监测网络状态,出错即关闭网络并重新初始化
参数: 无
返回: 无
调用:
char netCloseAll(int mode)
被调用:
void netInit();
**********************************************************************/
void netCheckLink()
{
/*由于优先极高,因此先创建信号灯才会进行网络的接收和发送*/
semCmdLink = semBCreate(SEM_Q_FIFO,SEM_EMPTY);
/*等待send()和recv()出错释放信号灯*/
semTake(semCmdLink,WAIT_FOREVER);
/*获得信号灯,表示网络连接断开*/
semDelete(semCmdLink);
taskSpawn(TNAME_NETCLOSEALL,TPRI_NETCLOSEALL,0,USER_STACK_SIZE,(FUNCPTR)netCloseAll,
MODE_NET_REINIT,0,0,0,0,0,0,0,0,0);
}