阅读:829回复:0
一个串口代理的小程序或叫串口server(LINUX)
实现通过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; } |
|