📄 netsvr.c
字号:
/**********************************************************************
chengjy@felab, copyright 2002-2004
netSvr.c
vxWorks作为server,双缓冲网络通讯,带网络监控,同时支持通讯协议
函数:
void netInit(int mode);
void netCMDRecv();
void netCMDExplain();
void netCMDSend();
void netCloseAll(int mode);
void netCheckLink();
char netCMDAdd(unsigned char *pBuff, int buffLen, int cmdNum, unsigned char priority);
char netRecvSize(unsigned char *pBuff, int len);
调用:
netTask.c
extern char t0x0200(unsigned char *pBuff);
extern char t0x0400(unsigned char *pBuff);
extern char t0x1600(unsigned char*pBuff);
netQueue.c
extern void queueInit();
extern char queueAdd(int index, unsigned char* pBuff, int pri);
extern char queueDelHead(int index);
extern char queueDelAll();
被调用:
用户程序初始化部分
netTask.c
**********************************************************************/
#include "vxWorks.h"
#include "taskLib.h"
#include "sockLib.h"
#include "ioLib.h"
#include "inetLib.h"
#include "logLib.h"
#include "string.h"
#include "fioLib.h"
#include "stdio.h"
#include "memLib.h"
#include "stdLib.h"
#include "semLib.h"
#include "netinet\\tcp.h"
#include "board.h"
/*通讯协议支持的命令*/
extern char t0x0200(unsigned char *pBuff); /*参数配置*/
extern char t0x0400(unsigned char *pBuff); /*reset*/
extern char t0x1600(unsigned char*pBuff); /*flash程序下载*/
/*缓冲队列操作*/
extern void queueInit();
extern char queueAdd(int index, unsigned char* pBuff, int pri);
extern char queueDelHead(int index);
extern char queueDelAll();
extern struct cmdSingle *queueHead[QUEUE_NUM];
int flagNetInit = NET_INIT_NULL; /*服务器初始化标志,程序中省略了对应的判断和操作*/
int listenSkt; /*命令通道侦听socket*/
int commuSkt; /*命令通道通讯socket*/
SEM_ID semQueueRecv; /*网络接收缓冲队列信号灯*/
SEM_ID semQueueSend; /*网络发送缓冲队列信号灯*/
SEM_ID semCmdLink; /*网络连接出错信号灯*/
void netInit(int mode);
void netCMDRecv();
void netCMDExplain();
void netCMDSend();
void netCloseAll(int mode);
void netCheckLink();
char netCMDAdd(unsigned char *pBuff, int buffLen, int cmdNum, unsigned char priority);
char netRecvSize(unsigned char *pBuff, int len);
/**********************************************************************
void netInit(int mode)
函数说明: 网络初始化程序
参数: mode, 分为MODE_NET_DEFAULT 和MODE_NET_REINIT 两种,
分别对应初始化侦听+通讯套接字和只
初始化通讯套接字两种。
返回: 无
调用:
void netCMDRecv();
void netCMDExplain();
void netCMDSend();
void netCheckLink();
netQueue.c:
extern void queueInit();
被调用: 用户程序初始化模块
void netCloseAll(int mode);
**********************************************************************/
void netInit(int mode)
{
struct sockaddr_in serverAddr;
struct sockaddr_in clientAddr;
int sockAddrSize;
int i;
char optval = 1;
/*建立本地的侦听用套接字listenSkt 并bind和listen*/
if(flagNetInit==NET_INIT_COMMUSKT)
return;
if((mode == MODE_NET_DEFAULT) && (flagNetInit == NET_INIT_NULL))
{
if((listenSkt = socket (AF_INET, SOCK_STREAM, 0)) == ERROR)
{
logMsg("netInit: can not open listen socket\n",0,0,0,0,0,0);
return;
}
sockAddrSize = sizeof (struct sockaddr_in);
bzero ((char *) &serverAddr, sockAddrSize);
serverAddr.sin_family = AF_INET;
serverAddr.sin_len = (u_char) sockAddrSize;
serverAddr.sin_port = htons (LOCAL_SERVER_PORT);
serverAddr.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind (listenSkt, (struct sockaddr *) &serverAddr, sockAddrSize) == ERROR)
{
logMsg("netInit:unable to bind to port %d\n",LOCAL_SERVER_PORT,0,0,0,0,0);
close(listenSkt);
return;
}
logMsg("netInit: successfully bind to port\n",LOCAL_SERVER_PORT,0,0,0,0,0);
if (listen (listenSkt, 1) == ERROR)
{
logMsg("netInit: can not listen to listen socket\n",0,0,0,0,0,0);
close (listenSkt);
return;
}
flagNetInit=NET_INIT_LISTENSKT;
}
/*接收外部联接,建立通讯套接字commuSkt*/
if(flagNetInit==NET_INIT_LISTENSKT)
{
sockAddrSize = sizeof (struct sockaddr_in);
commuSkt = accept(listenSkt, (struct sockaddr*)(&clientAddr), &sockAddrSize);
if(commuSkt==ERROR)
{
logMsg("netInit: can not accept command socket\n",0,0,0,0,0,0);
close (listenSkt);
return;
}
setsockopt (commuSkt, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof (optval));
/*初始化网络通讯的缓冲对列*/
queueInit();
/*初始化缓冲队列的计数型信号灯*/
semQueueSend = semCCreate(SEM_Q_FIFO,0);
semQueueRecv = semCCreate(SEM_Q_FIFO,0);
if((semQueueSend==NULL) ||(semQueueRecv==NULL))
{
semDelete(semQueueSend);
semDelete(semQueueRecv);
}
/*发起网络命令循环接收任务、命令解释任务、命令发送任务和网络监控任务*/
taskSpawn(TNAME_NETCHECKLINK,TPRI_NETCHECKLINK,0,USER_STACK_SIZE,
(FUNCPTR)netCheckLink,0,0,0,0,0,0,0,0,0,0);
taskSpawn(TNAME_NETRECV,TPRI_NETRECV,0,USER_STACK_SIZE,
(FUNCPTR)netCMDRecv,0,0,0,0,0,0,0,0,0,0);
taskSpawn(TNAME_NETEXPLAIN,TPRI_NETEXPLAIN,0,USER_STACK_SIZE,
(FUNCPTR)netCMDExplain,0,0,0,0,0,0,0,0,0,0);
taskSpawn(TNAME_NETSEND,TPRI_NETSEND,0,USER_STACK_SIZE,
(FUNCPTR)netCMDSend,0,0,0,0,0,0,0,0,0,0);
flagNetInit = NET_INIT_COMMUSKT;
logMsg("netInit: netInit finished\n",0,0,0,0,0,0);
}
}
/**********************************************************************
void netCMDRecv()
函数说明: 信息接收任务。循环从网络获得信息,打包后
添加到缓冲队列,等待信息解释任务处理。
参数: 无
返回: 无
调用:
char netRecvSize(unsigned char *pBuff, int len)
netQueue.c
char queueAdd(int index, unsigned char* pBuff, int pri);
被调用:
void netInit()
**********************************************************************/
void netCMDRecv()
{
unsigned char buff[8];
unsigned char *pBuff;
int lenAll;
char pri;
char state=STATUS_NORMAL;
int i;
/* 循环接收*/
while(1)
{
if(netRecvSize(buff,8)!=STATUS_NORMAL)
{
logMsg("netCMDRecv: error in head Recv netRecvSize(buff,8)\n",0,0,0,0,0,0);
break;
}
else
{
#ifdef LOG_NETMSG_HEAD
printf("netCMDRecv: print out head 8 bytes\n");
for(i=0;i<8;i++)
printf("0x%02x ",buff[i]);
printf("\n");
#endif
/*计算需要缓冲的总长度*/
lenAll = ((buff[2]*0x1000000)&0xFF000000)+((buff[3]*0x10000)&0xFF0000)
+((buff[4]*0x100)&0xFF00)+buff[5]; /*单条命令的总长度*/
pBuff = malloc(lenAll*sizeof(char));
if(pBuff!=NULL)
{
memcpy(pBuff,buff,8*sizeof(char));
if(lenAll>8)
{
state = netRecvSize(pBuff+8,lenAll-8);
if(state!=STATUS_NORMAL)
{
logMsg("netCMDRecv: error in rear part recv netRecvSize(pBuff,%d)\n",lenAll-8,0,0,0,0,0);
break;
}
}
/*正确接收了所有数据,添加到接收缓冲队列中*/
if(state== STATUS_NORMAL)
{
queueAdd(QUEUE_INDEX_RECV, pBuff, buff[6]);
semGive(semQueueRecv);
}
}
}
}
logMsg("netCMDRecv: something wrong, now exit\n",0,0,0,0,0,0);
}
/**********************************************************************
void netCMDExplain()
函数说明: 主循环消息处理和状态发送任务。循环获取信号灯
获取成功后, 根据命令号执行相应任务。
参数: 无
返回: 无
调用:
netQueue.c
char queueDelHead();
netTask:
STATUS t0xXXXX(char *pBuff);
被调用:
void netInit()
**********************************************************************/
void netCMDExplain()
{
unsigned char *pBegin;
int CMDNum;
char state;
while(semTake(semQueueRecv,WAIT_FOREVER)== OK)
{
/*从队头取出信息*/
pBegin = queueHead[QUEUE_INDEX_RECV]->pBuff;
CMDNum = pBegin[0]*0x100+pBegin[1];
/*这里只是示意性地作了几个命令的解释,用户应该根据
自己的通讯协议再添加内容*/
switch(CMDNum)
{
case 0x0200:
state = t0x0200(pBegin);
break;
case 0x0400:
state = t0x0400(pBegin);
break;
case 0x1600:
state = t0x1600(pBegin);
break;
default:
logMsg("netCMDExplain: command 0x%04x is not supported\n",CMDNum,0,0,0,0,0);
break;
}
if(state == STATUS_NORMAL)
logMsg("netCMDExplain: result of command 0x%04x is *OK*\n",CMDNum,0,0,0,0,0);
else
logMsg("netCMDExplain: result of command 0x%04x is *ERROR*\n",CMDNum,0,0,0,0,0);
free(pBegin);
queueDelHead(QUEUE_INDEX_RECV);
}
logMsg("netCMDExplain: error in taking semQueue\n",0,0,0,0,0,0);
}
/**********************************************************************
void netCMDSend()
函数说明: 循环从网络发送缓冲队列中取出数据并发送
参数: 无
返回: 无
调用:
netQueue.c
char queueDelHead(int index);
被调用:
netTask.c
char t0xXXXX(char *pBuff);
**********************************************************************/
void netCMDSend()
{
unsigned char *pBegin;
int lenAll,remainLen,realLen;
while(semTake(semQueueSend,WAIT_FOREVER)!=ERROR)
{
/*从队头取出信息*/
pBegin = queueHead[QUEUE_INDEX_SEND]->pBuff;
lenAll = ((pBegin[2]*0x1000000)&0xFF000000)+((pBegin[3]*0x10000)&0xFF0000)
+((pBegin[4]*0x100)&0xFF00)+pBegin[5]; /*单条命令的总长度*/
/*循环发送,直到发送完毕或者出错为止*/
remainLen = lenAll;
while(remainLen>0)
{
if(remainLen>NET_MSG_MAX_SIZE)
{
realLen = send(commuSkt,pBegin+lenAll-remainLen,NET_MSG_MAX_SIZE,0);
}
else
{
realLen = send(commuSkt,pBegin+lenAll-remainLen,remainLen,0);
}
if(realLen== ERROR)
{
logMsg("netCMDSend: unable to send command\n",0,0,0,0,0,0);
semGive(semCmdLink);
break;
}
remainLen = remainLen-realLen;
}
/*结束发送,释放空间*/
free(pBegin);
queueDelHead(QUEUE_INDEX_SEND);
if(remainLen!=0) /*发送出错,中途跳出的情况*/
break;
}
logMsg("netCMDSend: something wrong, now exit\n",0,0,0,0,0,0);
}
/**********************************************************************
void netCloseAll(int mode)
函数说明: 函数说明: 关闭侦听socket ,并删除命令缓冲
队列以及与socket相关的任务,并根据模式的
不同选择是直接关闭侦听套接字 (MODE_NET_DEFAULT)
还是重新初始化网络(MODE_NET_REINIT)
参数: mode, 选择关闭方式
返回: 无
调用:
void netInit(int mode);
netQueue.c
char queuDelAll();
被调用:
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_NETEXPLAIN);
if(taskId!=taskIdSelf() && taskId!=ERROR)
{
taskDelete(taskId);
}
taskId = taskNameToId(TNAME_NETCHECKLINK);
if(taskId!=taskIdSelf() && taskId!=ERROR)
{
taskDelete(taskId);
}
/*删除缓冲队列*/
queueDelAll();
/*删除缓冲队列的信号灯*/
semDelete(semQueueRecv);
semDelete(semQueueSend);
/*删除网络通断检测用信号灯*/
semDelete(semCmdLink);
/*根据网络初始化的不同状态作相应的退出工作*/
if(mode==MODE_NET_DEFAULT)
{
close(commuSkt);
close(listenSkt);
flagNetInit = NET_INIT_NULL;
}
else if(mode==MODE_NET_REINIT)
{
close(commuSkt);
flagNetInit = NET_INIT_LISTENSKT;
/*重新初始化网络*/
logMsg("netCloseAll: reInitialize net server\n",0,0,0,0,0,0);
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()
函数说明: 监测网络状态,出错即关闭网络并重新初始化
参数: 无
返回: 无
调用:
void 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);
}
/**********************************************************************
char netRecvSize(unsigned char *pBuff, int len)
函数说明: 底层函数,从网络接收数据
参数: pBuff, 接收数据存储的地方
len, 需要接受的总长度
返回: 正确执行返回STATUS_NORMAL,否则返回错误
调用: 无
被调用: void netCMDRecv();
**********************************************************************/
char netRecvSize(unsigned char *pBuff, int len)
{
int recvLen,remainLen;
if((len<=0) || (flagNetInit!=NET_INIT_COMMUSKT))
return(STATUS_INVALID);
else
remainLen = len;
while(remainLen>0)
{
recvLen = recv(commuSkt,pBuff+len-remainLen, remainLen,0);
if( (recvLen==ERROR) || (recvLen ==0) )
{
semGive(semCmdLink);
return(STATUS_ERROR);
}
remainLen = remainLen-recvLen;
}
return(STATUS_NORMAL);
}
/**********************************************************************
char netCMDAdd(unsigned char *pBuff, int buffLen, int cmdNum, unsigned char priority)
函数说明: 添加内容到发送缓冲队列
参数: pBuff, 需要经过修改后添加的数组首地址
buffLen, 数组长度,单位为byte
cmdNum,命令号
priority, 优先级
返回: 添加成功返回STATUS_NORMAL,否则返回错误
调用:
netQueue.c
char queueAdd(int index, unsigned char* pBuff, int pri)
被调用:
netTask.c
char t0xXXXX(char *pBuff);
**********************************************************************/
char netCMDAdd(unsigned char *pBuff, int buffLen, int cmdNum, unsigned char priority)
{
pBuff[0] = (cmdNum&0xFF00)>>8;
pBuff[1] = cmdNum&0x00FF;
pBuff[2] = ((buffLen>>24)&0xFF);
pBuff[3] = ((buffLen>>16)&0xFF);
pBuff[4] = ((buffLen>>8)&0xFF);
pBuff[5] = (buffLen&0xFF);
pBuff[6] = priority;
pBuff[7] = 0;
queueAdd(QUEUE_INDEX_SEND, pBuff, priority);
semGive(semQueueSend);
return(STATUS_NORMAL);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -