Chinaunix首页 | 论坛 | 博客
  • 博客访问: 22119
  • 博文数量: 10
  • 博客积分: 330
  • 博客等级: 一等列兵
  • 技术积分: 75
  • 用 户 组: 普通用户
  • 注册时间: 2009-06-01 12:12
文章存档

2011年(1)

2009年(9)

我的朋友
最近访客

分类: C/C++

2009-06-01 13:29:48

/**********************************************************************************

以下实现TCP的客户端和服务端通信,使用同一条TCP连接每隔5秒发一次“hello!”,直到网络故障或者强制程序退出,如果客户端异常退出,可以通过守护进程自动重启。

此程序参照《UNIX网络编程》,头文件直接使用书中打包好的头(做了一些修改)

env:

我的服务端是在这里跑的:

HP-UX hp94 B.11.11 U 9000/800 4183772791 unlimited-user license

客户端是在这里跑的:

Linux iprn215 2.4.21-32.EL #1 Fri Apr 15 21:29:19 EDT 2005 i686 i686 i386 GNU/Linux

服务端配置文件:

LISTEN_PORT  60005

客户端配置文件:

TCPTEST_SERADDR 192.168.2.89
TCPTEST_SERPORT 60005

说明:为了测试网络闪断,本来想找个现成的TCP通信程序,但是在网络上的示例程序都是使用一个socket做一次收发操作,然后就close掉 了。所以,只能硬着头皮自己写了。参照《UNIX网络编程》写,在我写守护的时候,按照书上的经典例程做,结果出了一个“疯狂的进程”,无论我想什么办法 都杀不死,现在还在疯狂地活着,(我迟早要kill了它!呵呵....)不过,最后经过几天的研究终于实现了基本功能,但是对自己程序的稳定性还是没什么 底呀!要是有哪位高手给予指点,不胜感激,感激涕零呀。。。。。。

最后要说的就是,我的程序估计很拙劣,但是希望抛砖引玉,得到大家的指点,另外,如果有人也有跟我曾经一样的烦恼,找不到一个合适的例子,希望我的砖头能帮点忙!

^_^

**********************************************************************************/

Server端:

/*包含一个init,它启动server,并使server后台运行而不占用此windows终端*/

server / init :

#include "unp.h"

#include "error.c"

#include "wrap.c"

void myinit()

{

 char filename[50];

 char *cinDir = getenv("CINDIR");

 if(cinDir == NULL)

  exit(0);

 if(fork() == 0)

 {

  memset(filename, 0, sizeof(filename));

  sprintf(filename,  "%s/bin/tcptest_server", cinDir);

  chdir("/");

  umask(0);

  execlp(filename, "tcptest_server", (char *)0);

  _exit(0);

 }

}

int main(void)

{

 void sig_chld(int); 

 if(fork()!=0)  _exit(0);

 //init进程中:

 setsid();

 myinit();

  exit(0);  //这个守护的目的就是使server脱离终端

}

server / TcpServer.c :

#include "wrap.c"

#define MAXLISTENNUM   10
int lineNUM = 0;

void writeLog(const char *fmt, ...);
void changeLogFile();

void alarmFunc(int signo)
{
 writeLog("receive client msg timeout !\n");
 exit(0);    //如果收消息超时,处理此client的子进程退出
}

void sig_chld(int signo)
{
 pid_t pid;
 int stat;
 while((pid = waitpid(-1, &stat, WNOHANG)) > 0)
 {
  //printf("child %d terminated ! \n", pid);
  writeLog("socket terminated : %d", pid);
 }
 signal(SIGCHLD, sig_chld);
}

void writeLog(const char *fmt, ...)
{
 time_t timer;
 struct tm *ptm;
 char wDay[20];
 int n;
  char buf[256];
  char logfilename[50];
  FILE *fp;
 char *cinDir = getenv("CINDIR");
 sprintf(logfilename, "%s/log/tcptest_server.log", cinDir);                       
 if((fp = fopen(logfilename, "a+")) == NULL)
 {                     
  printf("open log file error ! \n");
  exit(0);            
 }
   
  timer = time(NULL);
  ptm = localtime(&timer);
  memset(wDay, 0, sizeof(wDay));
  switch (ptm->tm_wday)
 {
  case 0: strcpy(wDay, "Sunday"); break;
  case 1: strcpy(wDay, "Monday"); break;
  case 2: strcpy(wDay, "Tuesday"); break;
  case 3: strcpy(wDay, "Wednesday"); break;
  case 4: strcpy(wDay, "Thursday"); break;
  case 5: strcpy(wDay, "Friday"); break;
  case 6: strcpy(wDay, "Saturday"); break;
 }
 
  memset(buf, 0, sizeof(buf));
  sprintf(buf, "%04d/%02d/%02d  %s  %02d:%02d:%02d | ",
                   (1900 + ptm->tm_year),
                   ptm->tm_mon,
                   ptm->tm_mday,
                   wDay,
                   ptm->tm_hour,
                   ptm->tm_min,
                   ptm->tm_sec);
 
  n = strlen(buf);
  va_list ap;
 va_start(ap, fmt);
#ifdef HAVE_VSNPRINTF
    vsnprintf(buf+n, 256, fmt, ap);
#else
    vsprintf(buf+n, fmt, ap);
#endif
  va_end(ap);

 fprintf(fp, buf, strlen(buf));
 fprintf(fp, "\r\n");
 fclose(fp);
 lineNUM++;
 //printf("linenum: %d \n", lineNUM);
 changeLogFile();
 return;
}

void changeLogFile()
{
 char logfilename[50];
  FILE *fp;
 char *cinDir = getenv("CINDIR");
 sprintf(logfilename, "%s/log/tcptest_server.log", cinDir);                       

 if(lineNUM > 30000)
 {
  lineNUM = 0;
  char oldfilename[256];
  char newfilename[256];
  
  time_t timer;
   struct tm *ptm;

   timer = time( NULL );
   ptm = localtime( &timer );
   sprintf(oldfilename,"%s.%04d%02d%02d%02d%02d",logfilename,(int)ptm->tm_year+1900,(int)ptm->tm_mon+1,(int)ptm->tm_mday,
        (int)ptm->tm_hour,(int)ptm->tm_min);
   unlink(oldfilename);
   rename(logfilename, oldfilename);
  
   if((fp = fopen(logfilename, "wt")) == NULL)
   printf("can not open log file : %s \n", logfilename);
   else
    fclose(fp);
 }
}

int main(int argc, char *argv[])
{
  int sockfd, clientfd;
  time_t timer;
  struct tm *ptm;
  char str[100];
  pid_t pid;
  pid_t childpid;
  struct sockaddr_in serveraddr;
  struct sockaddr_in clientaddr;
#ifdef _AIX
 socklen_t  sin_size;     /* 234 mod for ibmtest*/
#elif _LINUX
 socklen_t     sin_size;
#else
 int sin_size;
#endif
  //int sin_size;
  int n;
  char buf[8]; 
   void sig_chld(int);
   printf("||------------------------------------------\n");
   printf("||----tcptest server begin init ... \n");
  
  FILE *cfgfp;
  char *cinDir = getenv("CINDIR");
  char cfgfilename[100];
  sprintf(cfgfilename, "%s/etc/tcptest_server.config", cinDir);
  cfgfp = fopen(cfgfilename, "rt");
  if(cfgfp == NULL )
  {
    printf("can not open config file !\n");
    exit(1);
  }

  int listenport = 0;
  char temp[256];
  fscanf(cfgfp, "%s", temp);
  if(strcmp(temp, "LISTEN_PORT") == 0)
  {
    fscanf(cfgfp, "%s", temp);
    listenport = atoi(temp);
  }
  else
    printf("read config error!\n");
  fclose(cfgfp);
  
  printf("||----read config ok !\n");
  
  signal(SIGCHLD, sig_chld);
  
  //创建socket
  if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  {
    //fprintf(logfp, "creat socket error !");
    writeLog("creat socket error : %s!", strerror(errno));
    exit(1);
  }
  printf("||----create socket ok! \n");
  
  //填充结构
  bzero(&serveraddr, sizeof(struct sockaddr_in));
  serveraddr.sin_family = AF_INET;
  serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
  serveraddr.sin_port = htons(listenport);
  
  //bind         
  if(bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr)) < 0)
  {
    //fprintf(logfp, "bind error !\n");
    writeLog("bind error : %s !", strerror(errno));
    exit(1);
  }
  
  printf("||----bind socket ok ! \n");
  
  //listen
  if(listen(sockfd, MAXLISTENNUM))
  {
    //fprintf(logfp, "listen error !\n");
    writeLog("listen error : %s !", strerror(errno));
    exit(1);
  }
  
  printf("||----listen socket ok ! \n");
  printf("||------------------------------------------\n");
  for(;;)
  {
   sin_size=sizeof(struct   sockaddr_in);
   if((clientfd = accept(sockfd, (struct sockaddr *)&clientaddr, &sin_size)) < 0)
   {
    if(errno == EINTR)
     continue;
    else
    {
     //fprintf(logfp, "accept error !\n");
     writeLog("accept error : %s !", strerror(errno));
     exit(1);
    }
   }
   writeLog(" accept ok : client : %d!", clientfd);
   
   if((childpid = fork()) == 0)
   {
        writeLog("the child server fork ok : %d ! \n", getpid());
    close(sockfd);
    signal(SIGALRM,alarmFunc); 
    alarm(10);   //如果客户端异常退出,那么这里读超时.超时时间是8秒
    while((n = Read(clientfd, buf, MAXLINE)) != -1)  //对端正常终止(显示close)这里才会读-1, 如果对端ctrl+c,那么这里不会走正常的终止序列
    {
     if(n >0){
      alarm(10);
      Write(clientfd, buf, n);
      writeLog("receive and send msg : %s", buf);
      if(strcmp(buf, "hello!") != 0)
       writeLog("receive string error : %s ", buf);
      }
      else                         //如果对端没有数据输入,这里是0
            continue;
    }
    exit(0);
   }
   close(clientfd);
  }
  exit(0);
}

 

client端:

client / init :

int initNUM = 0;

void myinit(int initflag)
{
 char filename[50];
 char *cinDir = getenv("RNDIR");
 if(cinDir == NULL)
  exit(0);
 if(initflag == 1)
  sleep(5);
 if(initflag == 2)
  sleep(10);
 if(initflag == 3)
  sleep(20);
 if(initflag == 4)
  sleep(40);
  
 if ( fork() == 0 )
 {
  memset(filename, 0, sizeof(filename));
  sprintf(filename,  "%s/bin/tcptest_client", cinDir);
  chdir("/");
  umask(0);
  execlp(filename, "tcptest_client", (char *)0);

  _exit(0);
 }
}

void sig_chld(int signo)  //子进程结束才能进到这里
{
 pid_t pid;
 int stat;
 signal(SIGCHLD, sig_chld);
 
 while((pid = waitpid(-1, &stat, WNOHANG)) > 0)
 {
  initNUM++;    //如果客户端连接失败,那么子进程会退出,在这里试图重启12次
  if(initNUM > 4)
  {
   //exit(0);          //让它一直连,直到连上为止,或者强制退出
   initNUM = 0;
  }
  myinit(initNUM);
 }
}

int main(void)
{
 void sig_chld(int); 

 //printf("the main pid : %d \n", getpid());
 
 if(fork()!=0)  _exit(0);
 //init进程中:
 signal(SIGCHLD, sig_chld);
 setsid();
 
 myinit(0);

 for(;;)
 {
  sleep(10);
 }
}

client / TcpClient.c :

#include "wrap.c"

void changeLogFile();
void writeLog(const char *fmt, ...);
int lineNUM = 0;

void sig_chld(int signo)  //子进程结束才能进到这里
{
 int i;
 pid_t pid;
 pid_t pPid;
 int stat;

 while((pid = waitpid(-1, &stat, WNOHANG)) > 0)
 {
  printf("the child terminal : %d \n", pid);   //根本进不来
 }

 exit(0);
}

void writeLog(const char *fmt, ...)
{
 time_t timer;
 struct tm *ptm;
 char wDay[20];
 int n;
  char buf[256];
  char logfilename[50];
  FILE *fp;
 char *cinDir = getenv("RNDIR");
 sprintf(logfilename, "%s/log/tcptest_client.log", cinDir);                       
 if((fp = fopen(logfilename, "a+")) == NULL)
 {                     
  printf("open log file error ! \n");
  exit(0);            
 }
   
  timer = time(NULL);
  ptm = localtime(&timer);
  memset(wDay, 0, sizeof(wDay));
  switch (ptm->tm_wday)
 {
  case 0: strcpy(wDay, "Sunday"); break;
  case 1: strcpy(wDay, "Monday"); break;
  case 2: strcpy(wDay, "Tuesday"); break;
  case 3: strcpy(wDay, "Wednesday"); break;
  case 4: strcpy(wDay, "Thursday"); break;
  case 5: strcpy(wDay, "Friday"); break;
  case 6: strcpy(wDay, "Saturday"); break;
 }
 
  memset(buf, 0, sizeof(buf));
  sprintf(buf, "%04d/%02d/%02d  %s  %02d:%02d:%02d | ",
                   (1900 + ptm->tm_year),
                   ptm->tm_mon,
                   ptm->tm_mday,
                   wDay,
                   ptm->tm_hour,
                   ptm->tm_min,
                   ptm->tm_sec);
 
  n = strlen(buf);
  va_list ap;
 va_start(ap, fmt);
#ifdef HAVE_VSNPRINTF
    vsnprintf(buf+n, 256, fmt, ap);
#else
    vsprintf(buf+n, fmt, ap);
#endif
  va_end(ap);

 fprintf(fp, buf, strlen(buf));
 fprintf(fp, "\r\n");
 fclose(fp);
 lineNUM++;
 //printf("linenum: %d \n", lineNUM);
 changeLogFile();
 return;
}

void changeLogFile()
{
 char logfilename[50];
  FILE *fp;
 char *cinDir = getenv("RNDIR");
 sprintf(logfilename, "%s/log/tcptest_client.log", cinDir);                       

 if(lineNUM > 30000)
 {
  lineNUM = 0;
  char oldfilename[256];
  char newfilename[256];
  
  time_t timer;
   struct tm *ptm;

   timer = time( NULL );
   ptm = localtime( &timer );
   sprintf(oldfilename,"%s.%04d%02d%02d%02d%02d",logfilename,(int)ptm->tm_year+1900,(int)ptm->tm_mon+1,(int)ptm->tm_mday,
        (int)ptm->tm_hour,(int)ptm->tm_min);
   unlink(oldfilename);
   rename(logfilename, oldfilename);
  
   if((fp = fopen(logfilename, "wt")) == NULL)
   printf("can not open log file : %s \n", logfilename);
   else
    fclose(fp);
 }
}

int
main(int argc, char **argv)
{
 int                  i, sockfd;
 int port;
 char address[21] = "127.0.0.1";
 struct sockaddr_in   servaddr;
 
 char sendbuf[8];
 sprintf(sendbuf, "hello!");
 char recvbuf[10];

 char cfgfilename[50];
 FILE *cfgfp;
 char *cinDir = getenv("RNDIR");
 sprintf(cfgfilename, "%s/config/tcptest_client.config", cinDir);
                  
 if((cfgfp = fopen(cfgfilename, "a+")) == NULL)
 {                     
  printf("open config file error ! \n");
  exit(0);
 }

 char temp[256];
 while(fscanf(cfgfp, "%s", temp) != EOF)
 {
  if(strcmp(temp, "TCPTEST_SERADDR") == 0)
  {
   memset(address, 0, sizeof(address));
   fscanf(cfgfp, "%s", address);
  }
   else if(strcmp(temp, "TCPTEST_SERPORT") == 0)
    fscanf(cfgfp, "%d", &port);
   else
   printf("read config error!\n");
 }
 fclose(cfgfp);
  
 sockfd = Socket(AF_INET, SOCK_STREAM, 0);
 
 bzero(&servaddr, sizeof(servaddr));
 servaddr.sin_family = AF_INET;
 servaddr.sin_port = htons(port);
 Inet_pton(AF_INET, address, &servaddr.sin_addr.s_addr);
 
 writeLog("connect server begin ......");
 
 if(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
 {
  writeLog("connect server error : %s !", strerror(errno));
  exit(0);
 }
 
 writeLog("connect server ok !  \n");
 
 for(;;)
 {
  Write(sockfd, sendbuf, 8);
  Read(sockfd,  recvbuf, 10);
  //fprintf(stdout, "%s", recvbuf);
  writeLog("receive msg : %s", recvbuf);
  if(strcmp(recvbuf, "hello!") != 0)
   writeLog("receive string error : %s ", recvbuf);
  sleep(5);
 }
 close(sockfd);

 _exit(0);
}

阅读(740) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:使用ifstream和getline读取文件内容[c++]

给主人留下些什么吧!~~