niliab
驱动牛犊
驱动牛犊
  • 注册日期2002-11-03
  • 最后登录2002-11-03
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:829回复:0

一个串口代理的小程序或叫串口server(LINUX)

楼主#
更多 发布于:2002-11-03 01:00
实现通过telnet控制串口,如本机上有10个串口(假如有个moxa卡),
启动本程序后,其他计算机
telnet 本机IP 2001
则表示控制com1,依次类推。
本程序为一deamon进程,使用多进程对多个串口进行控制
编译:
gcc -lpthread -o comagent comagent.c
源码:
comagent.c

#include \"unistd.h\"
#include \"string.h\"
#include \"stdarg.h\"
#include \"sys/socket.h\"
#include \"netinet/in.h\"
#include \"signal.h\"
#include \"stdio.h\"
#include <sys/types.h>
#include <sys/stat.h>
#include \"wait.h\"
#include \"error.h\"
#include \"errno.h\"
#include <fcntl.h>
#include \"stdlib.h\"
#include \"pthread.h\"

#define SERVER_PORT 2001
#define BACKLOG 2

#define MAX_COM_NUM  20

typedef struct _str_COM
{
int iComID;
char szDevName[32];
int iComFd;
int iConnFd;
int iServerFd;
int iIsInUse;
struct sockaddr_in ClientAddr;
}ManagerCOM;

ManagerCOM gMCOM[MAX_COM_NUM];

FILE *gpLogFile = NULL;

void TaskEntry(void *pArg)
{
ManagerCOM *pMCom;
char szBufIn[1024],szBufOut[1024];
int iReadBytes;
fd_set RdSet;
struct timeval TmVal;
int iMaxFd;

pMCom = (ManagerCOM *)pArg;

LogMsg(7,\"FileHandle %d\",pMCom->iComFd);

TmVal.tv_sec = 60000;
TmVal.tv_usec = 0;
if(pMCom->iConnFd > pMCom->iComFd)
{
iMaxFd = pMCom->iConnFd;
}
else
{
iMaxFd = pMCom->iComFd;
}

while(1)
{
int iSelRet;

FD_ZERO(&RdSet);
FD_SET(pMCom->iConnFd,&RdSet);
FD_SET(pMCom->iComFd,&RdSet);

iSelRet = select(iMaxFd + 1,&RdSet,NULL,NULL,&TmVal);

if(iSelRet < 0)
{
continue;
}
if(iSelRet == 0)
{
break;
}

if(FD_ISSET(pMCom->iConnFd,&RdSet))
{
iReadBytes = read(pMCom->iConnFd,szBufIn,1024);
if(iReadBytes > 0)
{
/*LogMsg(6,\"%s\",szBufIn);*/
write(pMCom->iComFd,szBufIn,iReadBytes);
}
else if(iReadBytes == 0)
{
break;
}
}

if(FD_ISSET(pMCom->iComFd,&RdSet))
{
iReadBytes = read(pMCom->iComFd,szBufOut,1024);
if(iReadBytes > 0)
{
/*LogMsg(6,\"%s\",szBufOut);*/
if(write(pMCom->iConnFd,szBufOut,iReadBytes) < 0)
{
break;
}
}
}
}

/* if happen some error or client quit,then return */
LogMsg(7,\"happen some error or client quit!\");
pMCom->iIsInUse = 0;
close(pMCom->iComFd);
close(pMCom->iConnFd);
}

void MySigDo(int sig)
{
LogMsg(7,\"sig = %d\",sig);
ErrorExit(0);
}

void MCom_Init(void)
{
memset(gMCOM,0,MAX_COM_NUM*sizeof(ManagerCOM));

/* set signal handle function */
signal(SIGKILL,MySigDo);
signal(SIGABRT,MySigDo);
signal(SIGQUIT,MySigDo);
signal(SIGHUP,MySigDo);
signal(SIGTERM,MySigDo);

/* open log file */
gpLogFile = fopen(\"/var/log/comagent.log\",\"a+\");
if(!gpLogFile)
{
LogMsg(7,\"#Error open log file!\\n\");
}
else
{
/*open(\"/dev/null\",O_RDWR);
dup(0);
dup(1);
dup(2);*/
}
LogMsg(1,\"#success open log file!\");
}

int LogMsg(int level, const char *fmt, ...)
{
int iLength;
/* Guess we need no more than 128 bytes. */
int iSize = 128;
char *pszBuf;
va_list arg;

if ((pszBuf = malloc (iSize)) == NULL)
{
return -1;
}

while (1)
{
/* Try to print in the allocated space. */
va_start(arg, fmt);
iLength = vsnprintf (pszBuf, iSize, fmt, arg);
va_end(arg);
/* If that worked, return the string. */
if (iLength > -1 && iLength < iSize)
{
break;
}
/* Else try again with more space. */
if (iLength > -1)    /* glibc 2.1 */
{
iSize = iLength+1; /* precisely what is needed */
}
else           /* glibc 2.0 */
{
iSize *= 2;  /* twice the old size */
}

if ((pszBuf = realloc (pszBuf, iSize)) == NULL)
{
return -1;
}
}

if(gpLogFile)
{
iLength = fprintf(gpLogFile,\"%s\\n\",pszBuf);
fflush(gpLogFile);

}
else
{
iLength = fprintf(stderr,\"%s\\n\",pszBuf);
}

free(pszBuf);
pszBuf = NULL;

return (iLength);
}

int ErrorExit(int ErrNum)
{
int iIndex;

for(iIndex = 0;iIndex < MAX_COM_NUM;iIndex ++)
{
if(gMCOM[iIndex].iComFd > 0)
{
close(gMCOM[iIndex].iComFd);
}
if(gMCOM[iIndex].iConnFd > 0)
{
/*shutdown(gMCOM[iIndex].iConnFd,2);*/
close(gMCOM[iIndex].iConnFd);
}
if(gMCOM[iIndex].iServerFd > 0)
{
/*shutdown(gMCOM[iIndex].iServerFd,2);*/
close(gMCOM[iIndex].iServerFd);
}
}

if(gpLogFile)
{
fclose(gpLogFile);
}
exit(ErrNum);

return 0;
}

int Daemon_Init()
{
struct sigaction act;
int iIndex,iMaxFd;

if(fork() != 0)
{
exit(0);
}

if(setsid() < 0)
{
return -1;
}

/*act.sa_handler = SIG_IGN;
act.sa_mask = )0;
act.sa_flags = 0;
sigaction(SIGHUP,&act,0);

if(fork() != 0)
{
exit(0);
}*/

chdir(\"/\");
umask(0);

iMaxFd = sysconf(_SC_OPEN_MAX);
for(iIndex = 0;iIndex < iMaxFd;iIndex ++)
{
close(iIndex);
}

return 0;
}

int main(void)
{
int iIndex;
int ret;
int iConnFd;
int iMaxServerFd = 0;
struct sockaddr_in ServerAddr;
fd_set RdSet;
struct timeval TmVal;

if(Daemon_Init() < 0)
{
LogMsg(7,\"Daemon_Init Error!\");
exit(1);
}

MCom_Init();

FD_ZERO(&RdSet);

for(iIndex = 0;iIndex < MAX_COM_NUM;iIndex ++)
{
int iOptVal;

gMCOM[iIndex].iServerFd = socket(AF_INET,SOCK_STREAM,0);
if(gMCOM[iIndex].iServerFd < 0)
{
fprintf(stderr,\"Socket Error!\\n\");
ErrorExit(1);
}

errno = 0;
iOptVal = 1;
/* set server port to reuse port */
if(setsockopt(gMCOM[iIndex].iServerFd,SOL_SOCKET,SO_REUSEADDR,&iOptVal,sizeof(int)) < 0)
{
LogMsg(7,\"setsockopt Error,return errno is %d\",errno);
}

bzero(&ServerAddr,sizeof(ServerAddr));
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
ServerAddr.sin_port = htons(SERVER_PORT + iIndex);

errno = 0;
if(bind(gMCOM[iIndex].iServerFd,(struct sockaddr *)&ServerAddr,sizeof(ServerAddr)) < 0)
{
LogMsg(7,\"Bind Error,return errno is %d\",errno);
ErrorExit(1);
}

if(listen(gMCOM[iIndex].iServerFd,BACKLOG) < 0)
{
LogMsg(7,\"Listen Error!\");
ErrorExit(1);
}

if(iMaxServerFd < gMCOM[iIndex].iServerFd)
{
iMaxServerFd = gMCOM[iIndex].iServerFd;
}
FD_SET(gMCOM[iIndex].iServerFd,&RdSet);
}

TmVal.tv_sec = 60;
TmVal.tv_usec = 0;
while(1)
{
int iSelRet;
fd_set tpRdSet;

tpRdSet = RdSet;
iSelRet = select(iMaxServerFd + 1,&tpRdSet,NULL,NULL,&TmVal);

if(iSelRet <= 0)
{
continue;
}

for(iIndex = 0;iIndex < MAX_COM_NUM;iIndex ++)
{
if(FD_ISSET(gMCOM[iIndex].iServerFd,&tpRdSet))
{
struct sockaddr ClientAddr;
int iAddrLen;

iConnFd = accept(gMCOM[iIndex].iServerFd,NULL,NULL);

if(iConnFd < 0)
{
fprintf(stderr,\"Accept Error!\\n\");
continue;
}
/* if the com has been used,then close connection */
if(gMCOM[iIndex].iIsInUse)
{
char szErrMsg[128];

LogMsg(7,\"the com has been used!\");
sprintf(szErrMsg,\"the com has been used by %s:%d!\",
inet_ntoa(gMCOM[iIndex].ClientAddr.sin_addr),
ntohs(gMCOM[iIndex].ClientAddr.sin_port));
write(iConnFd,szErrMsg,strlen(szErrMsg));
close(iConnFd);
continue;
}
gMCOM[iIndex].iConnFd = iConnFd;
getpeername(iConnFd,(struct sockaddr*)&ClientAddr,&iAddrLen);
memcpy(&gMCOM[iIndex].ClientAddr ,(struct sockaddr_in*)&ClientAddr,sizeof(struct sockaddr_in));
gMCOM[iIndex].szDevName[0] = \'\\0\';

if(iIndex < 2)
{
sprintf(gMCOM[iIndex].szDevName,\"/dev/ttyS%d\",iIndex);
}
else
{
sprintf(gMCOM[iIndex].szDevName,\"/dev/ttyA1%d\",(iIndex - 1));
}

LogMsg(7,\"Dev Name:%s\",(char*)gMCOM[iIndex].szDevName);
gMCOM[iIndex].iComFd = open(gMCOM[iIndex].szDevName,O_RDWR);

if(gMCOM[iIndex].iComFd > 0)
{
pthread_t id;

gMCOM[iIndex].iConnFd = iConnFd;
ret = pthread_create(&id,NULL,TaskEntry,(void *)(&gMCOM[iIndex]));
if(!ret)
{
gMCOM[iIndex].iIsInUse = 1;
LogMsg(7,\"success open com and create thread!\");
}
}
else
{
LogMsg(7,\"error open com!\");
}
}
}
}

ErrorExit(0);

return 0;
}
游客

返回顶部