Examples

This chapter describes the roles of TCPGWTHR using examples.

1. Server Mode Outbound Service Call

This section describes an example program that requests a Tmax service from the remote server through a server mode TCPGWTHR.

The example program consists of the following files.

Type File Name

Environment File

tmax.m

TCPGWTHR

usermain.c

Remote Node

tcpcli1.c

Tmax Node

svr.c

1.1. Environment File

< tmax.m >
*DOMAIN
res SHMKEY = 88000,
MINCLH = 1,
MAXCLH = 1,
TPORTNO = 8888

*NODE
node1TMAXDIR=”/home/tmax”,
APPDIR=”/home/tmax/appbin”

*SVRGROUP
svg1NODENAME = node1

*SERVER
tcpgwlsn  SVGNAME = svg1, MIN=1, MAX=1, SVRTYPE = CUSTOM_GATEWAY, RESTART = N,
          CLOPT="-- -P 9777 -N 3 -k 91000"
tcpgwhdr1 SVNAME = svg1, MIN=3, MAX=3, SCHEDULE=RR, SVRTYPE=CUSTOM_GATEWAY, CPC=10,
          TARGET  = tcpgwhdr,
          CLOPT="-- -P 9777 -N 10 -s –L tcpgwlsn"
svr        SVGNAME = svg1

*SERVICE
TESTSVC     SVRNAME = svr

1.2. TCPGWTHR

<usermain.c >
#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#include <io.h>
#else
#include <pthread.h>
#endif
#include <tcphdr.h>

int user_thrmain(WORKTHRINFO *winfo, int server)
{
  if (server)
     server_process(winfo);
  else
     client_process(winfo);

  return 1;
}

int server_process(WORKTHRINFO *winfo)
{
  int   n, len, flags;
  char  tmp[10];
  char  sndbuf[4096];
  char  rcvbuf[4096];
  long  rcvlen;
  int   errflag;

  memset(tmp, 0x00, sizeof(tmp));
  while (1) {
      n = tcpgw_select(winfo, 0, 0);
      if (n < 0)
         return -1;

      printf("tcpgw_select: n = %d\n", n);

      /* request ffrom tmax  service & client */
      switch(n) {
      case WTHR_TMAX_REQUEST:
           len = tcpgw_get_svcdata(winfo, &rcvbuf[4], &errflag, &flags);
           if (len < 0) {
              if (len == WTHR_CLIENT_CLOSE)
                 return -1;

              printf("service data read failed\n");
              return -1;
           }
           printf("TMAX_REQUEST: length = %d\n", len);

           /* no reply */
           if (flags)
              n = tcpgw_tpreply(winfo, rcvbuf, n, 0);

           sprintf(tmp, "%04d", len);
           memcpy(rcvbuf, tmp, 4);
           len += 4;

           n = tcpgw_write(winfo->fd, rcvbuf, len);
           if (n < 0) {
              printf("remote client closed\n");
              return -1;
           }
           printf("TMAX_REQUEST: remote write ok [%d]\n", n);

           n = tcpgw_read(winfo->fd, tmp, 4, 0, 0);
           if (n <= 0) {
              printf("remote client closed\n");
              return -1;
           }
           len = atoi(tmp);
           if (len <= 0)
              break;

           printf("TMAX_REQUEST: read length = %d\n", len);
           n = tcpgw_read(winfo->fd, rcvbuf, len, 0, 0);
           if (n <= 0) {
             printf("remote client closed\n");
             return -1;
           }

           if (flags) {
              printf("USER_REQUEST: service call length = %d\n", n);
              flags = 1;
              n = tcpgw_tpcall(winfo, "TESTSVC", rcvbuf, n, rcvbuf, &rcvlen);
           }
           else {
              printf("TMAX_REQUEST: tpcall reply length = %d\n", n);
              n = tcpgw_tpreply(winfo, rcvbuf, n, 0);
           }
           if (n < 0) {
              printf("tmax down\n");
              return -1;
           }
           break;

      case WTHR_USER_REQUEST:
           n = tcpgw_read(winfo->fd, tmp, 4, 0, 0);
           if (n <= 0) {
              printf("remote client closed\n");
              return -1;
           }
           len = atoi(tmp);
           if (len <= 0)
              break;

           printf("USER_REQUEST: read length = %d\n", len);
           n = tcpgw_read(winfo->fd, sndbuf, len, 0, 0);
           if (n <= 0) {
              printf("remote client closed\n");
              return -1;
           }

           printf("USER_REQUEST: service call length = %d\n", n);
           n = tcpgw_tpcall(winfo, "TESTSVC", sndbuf, n, rcvbuf, &rcvlen);
           if (n < 0) {
              printf("service failed: [%d]\n", n);
           }

           sprintf(tmp, "%04d", rcvlen);
           memcpy(sndbuf, tmp, 4);
           memcpy(&sndbuf[4], rcvbuf, rcvlen);
           len = rcvlen + 4;

           printf("USER_REQUEST: service reply length = %d\n", len);
           n = tcpgw_write(winfo->fd, sndbuf, len);
           if (n < 0) {
              printf("remote client closed\n");
              return -1;
           }
           break;

      case WTHR_SELECT_TIMEOUT:
           /* timeout process */
           break;
      }
}
  return 1;
}
int client_process(WORKTHRINFO *winfo)
{
  int   fd, portno;
char  ipaddr[20];

portno = tcpgw_getaddr_from_winfo(winfo, ipaddr);
  /* socket connect */
  while (1) {
      fd = tcpgw_network_connect(ipaddr, portno, 0);
      if (fd > 0)
         break;

      printf("remote connect failed\n");
#ifdef _WIN32
      Sleep(10000);
#else
      sleep(10);
#endif
      continue;
  }

  winfo->fd = fd;  /* must save */
  server_process(winfo);

  return 1;
}

1.3. Remote Node

<tcpcli1.c >
#include  <stdio.h>
#include  <stdlib.h>
#include  <string.h>

#ifdef _WIN32
#include  <winsock2.h>
#include  <windows.h>
#include  <io.h>
#else
#include  <unistd.h>
#include  <netdb.h>
#include  <sys/types.h>
#include  <sys/socket.h>
#include  <sys/un.h>
#include  <netinet/in.h>
#include  <arpa/inet.h>
#endif

#ifdef _WIN32
#define GW_ADDR   "host"
#else
#define GW_ADDR   "10.10.10.10"
#endif
#define GW_PORT   9777
#define NUM_LOOP  1
#define MAX_MSG   496

#if (defined(_SOCK1) || defined(_SOCK11))
#define _LOBYTE   1
#define _HIBYTE   1
#else
#define _LOBYTE   2
#define _HIBYTE   0
#endif

#ifdef _WIN32
int winsock_init(void)
{
  WORD wVersionRequested;
  WSADATA wsaData;
  int err;

  wVersionRequested = MAKEWORD(_LOBYTE, _HIBYTE);
  err = WSAStartup(wVersionRequested, &wsaData);
  if (err != 0) {
     /* Tell the user that we couldn't find a usable */
     /* WinSock DLL.                                  */
     printf("0060 Winsock startup error\n");
     return -1;
  }

  /* Confirm that the WinSock DLL supports 2.0.*/
  /* Note that if the DLL supports versions greater    */
  /* than 2.0 in addition to 2.0, it will still return */
  /* 2.0 in wVersion since that is the version we      */
  /* requested.                                        */
  if (LOBYTE(wsaData.wVersion) != _LOBYTE ||
      HIBYTE(wsaData.wVersion) != _HIBYTE) {
     /* Tell the user that we couldn't find a usable */
     /* WinSock DLL.                                  */
     WSACleanup();
     printf("0061 Winsock version check error\n");
     return -1;
  }
  /* The WinSock DLL is acceptable. Proceed. */

  return 1;
}
#endif

int _network_connect(char *host, int port)
{
  struct sockaddr_in  serv_addr;
  unsigned int  inaddr;
  struct hostent  *hp;
  int    i, fd;

  memset((char *) &serv_addr, 0, sizeof(serv_addr));
  serv_addr.sin_family      = AF_INET;
  serv_addr.sin_port        = htons(port);

  if ((inaddr = (unsigned int) inet_addr(host)) != -1) {
     memcpy((char *) &serv_addr.sin_addr, (char *) &inaddr,
     sizeof(struct in_addr));
  } else {
     if ((hp = gethostbyname(host)) == NULL) {
        printf("COM3412: host name error: %s ", host);
        return(-1);
     }
     memcpy((char *) &serv_addr.sin_addr, hp->h_addr,
     hp->h_length);
  }

  if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
     printf("COM3413: can't open stream socket");
     return -1;
  }

  if (connect(fd, (struct sockaddr *) &serv_addr,
        sizeof(serv_addr)) >= 0)
     return fd;

  close(fd);

  return -1;
}

int main(int argc, char *argv[])
{
  char  gw_addr[256], tmp[10];
  int gw_port, fd, i, n, len, num_loop;
  char  data[MAX_MSG];

  strcpy(gw_addr, GW_ADDR);
  gw_port = GW_PORT;
  num_loop = NUM_LOOP;
  if (argc == 2) {
      num_loop = atoi(argv[1]);
  } else if (argc == 3) {
      gw_port = atoi(argv[1]);
      num_loop = atoi(argv[2]);
  } else if (argc >= 4) {
      strcpy(gw_addr, argv[1]);
      gw_port = atoi(argv[2]);
      num_loop = atoi(argv[3]);
  }

#ifdef _WIN32
  winsock_init();
#endif

  fd = _network_connect(gw_addr, gw_port);
  if (fd < 0) {
      printf("Connect to (%s:%d) fail \n", gw_addr, gw_port);
      return -1;
  }

  sleep(5);
  memset(data, 0x00, MAX_MSG);
  for (i=0; i<num_loop; i++) {
      sprintf(&data[4], "Msg(%d) produced by PID(%d)", i, getpid());
      len = strlen(&data[4]);
      sprintf(tmp, "%04d", len);
      memcpy(data, tmp, 4);

      len += 4;
      n = send(fd, data, len, 0);
      if (n != len) {
          printf("Sent only %d / %d bytes\n", n, len);
          return -1;
      }

      len = 4;
      n = recv(fd, data, len, 0);
      if (n != len) {
    printf("Recv error %d\n", n);
          return -1;
      }

      memcpy(tmp, data, 4);
      tmp[4] = 0x00;
      len = atoi(tmp);
      if (len <= 0) {
         printf("Pid (%d) received %d bytes\n", getpid(), n);
         continue;
      }

      n = recv(fd, data, len, 0);
      if (n != len) {
          printf("Recv error %d\n", n);
          return -1;
      }
      printf("Pid (%d) received %d bytes\n",
          getpid(), n);
      sleep(5);
  }

  return 1;
}

1.4. Tmax Node

< svr.c >
#include <stdio.h>
#include <usrinc/atmi.h>

TESTSVC(TPSVCINFO *msg)
{
  inti;

  printf("TESTSVC service is started!\n");
  sleep(1);
  printf("OUTPUT: data=%.*s\n", msg->len, msg->data);
  printf("TESTSVC service is stoped!\n");
  tpreturn(TPSUCCESS,0,(char *)msg->data, msg->len, 0);
}

2. Server Mode Inbound Service Call

This section describes an example program that requests a remote service from Tmax through a server mode TCPGWTHR.

The example program consists of the following files.

Type File Name

Environment File

tmax.m, tcpgwthr.cfg

TCPGWTHR

usermain.c (Refer to Server Mode Outbound Service Call for a detailed example of this file.)

Remote Node

tcpcli2.c

Tmax Node

toupper.c

2.1. Environment File

< tmax.m >
*DOMAIN
Res SHMKEY = 88000,
MINCLH = 1,
MAXCLH = 1,
TPORTNO = 8888

*NODE
node1TMAXDIR=”/home/tmax”,
APPDIR=”/home/tmax/appbin”

*SVRGROUP
svg1NODENAME = node1

*SERVER
tcpgwlsn  SVGNAME = svg1, MIN=1, MAX=1, SVRTYPE = CUSTOM_GATEWAY, RESTART = N,
          CLOPT="-- -P 9777 -N 3 -k 91000 -F /home/tmax/appbin/tcpgwthr.cfg"

tcpgwhdr1 SVNAME = svg1, MIN=3, MAX=3, SCHEDULE=RR,SVRTYPE=CUSTOM_GATEWAY, CPC= 10,
          TARGET  = tcpgwhdr,
          CLOPT="-- -P 9777 -N 10 -s –L tcpgwlsn"

*SERVICE
svcgw     SVRNAME = tcpgwhdr1
< tcpgwthr.cfg >
# Client IP  Server Port Client ID
10.10.10.10    9777   SVR0001

2.2. Remote Node

< tcpcli2.c >
#include  <stdio.h>
#include  <stdlib.h>
#include  <string.h>

#ifdef _WIN32
#include  <winsock2.h>
#include  <windows.h>
#include  <io.h>
#else
#include  <unistd.h>
#include  <netdb.h>
#include  <sys/types.h>
#include  <sys/socket.h>
#include  <sys/un.h>
#include  <netinet/in.h>
#include  <arpa/inet.h>
#endif

#ifdef _WIN32
#define GW_ADDR   "host"
#else
#define GW_ADDR   "10.10.10.10"
#endif
#define GW_PORT   9777
#define NUM_LOOP  1
#define MAX_MSG   496

#if (defined(_SOCK1) || defined(_SOCK11))
#define _LOBYTE   1
#define _HIBYTE   1
#else
#define _LOBYTE   2
#define _HIBYTE   0
#endif

#ifdef _WIN32
int winsock_init(void)
{
  WORD wVersionRequested;
  WSADATA wsaData;
  int err;

  wVersionRequested = MAKEWORD(_LOBYTE, _HIBYTE);
  err = WSAStartup(wVersionRequested, &wsaData);
  if (err != 0) {
     /* Tell the user that we couldn't find a usable */
     /* WinSock DLL.                                  */
     printf("0060 Winsock startup error\n");
     return -1;
  }

  /* Confirm that the WinSock DLL supports 2.0.*/
  /* Note that if the DLL supports versions greater    */
  /* than 2.0 in addition to 2.0, it will still return */
  /* 2.0 in wVersion since that is the version we      */
  /* requested.                                        */
  if (LOBYTE(wsaData.wVersion) != _LOBYTE ||
      HIBYTE(wsaData.wVersion) != _HIBYTE) {
     /* Tell the user that we couldn't find a usable */
     /* WinSock DLL.                                  */
     WSACleanup();
     printf("0061 Winsock version check error\n");
     return -1;
  }
  /* The WinSock DLL is acceptable. Proceed. */

  return 1;
}
#endif

int _network_connect(char *host, int port)
{
  struct sockaddr_in  serv_addr;
  unsigned int  inaddr;
  struct hostent  *hp;
  int    i, fd;

  memset((char *) &serv_addr, 0, sizeof(serv_addr));
  serv_addr.sin_family      = AF_INET;
  serv_addr.sin_port        = htons(port);

  if ((inaddr = (unsigned int) inet_addr(host)) != -1) {
     memcpy((char *) &serv_addr.sin_addr, (char *) &inaddr,
     sizeof(struct in_addr));
  } else {
     if ((hp = gethostbyname(host)) == NULL) {
        printf("COM3412: host name error: %s ", host);
        return(-1);
     }
     memcpy((char *) &serv_addr.sin_addr, hp->h_addr,
     hp->h_length);
  }

  if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
     printf("COM3413: can't open stream socket");
     return -1;
  }

  if (connect(fd, (struct sockaddr *) &serv_addr,
        sizeof(serv_addr)) >= 0)
     return fd;

  close(fd);

  return -1;
}

int main(int argc, char *argv[])
{
  char  gw_addr[256], tmp[10];
  int gw_port, fd, i, n, len, num_loop;
  char  data[MAX_MSG];

  strcpy(gw_addr, GW_ADDR);
  gw_port = GW_PORT;
  if (argc == 2) {
      gw_port = atoi(argv[1]);
  }

#ifdef _WIN32
  winsock_init();
#endif

  fd = _network_connect(gw_addr, gw_port);
  if (fd < 0) {
      printf("Connect to (%s:%d) fail \n", gw_addr, gw_port);
      return -1;
  }

  memset(data, 0x00, MAX_MSG);
  while (1) {
      len = 4;
      n = recv(fd, data, len, 0);
      if (n != len) {
    printf("Recv error %d\n", n);
          return -1;
      }

      memcpy(tmp, data, 4);
      tmp[4] = 0x00;
      len = atoi(tmp);
      if (len <= 0) {
         printf("Pid (%d) received %d bytes\n", getpid(), n);
         continue;
      }

      n = recv(fd, &data[4], len, 0);
      if (n != len) {
          printf("Recv error %d\n", n);
          return -1;
      }
      printf("Pid (%d) received %d bytes\n", getpid(), n);

      len = n + 4;
      for (i = 4; i < len; i++)
          data[i] = toupper(data[i]);

      n = send(fd, data, len, 0);
      if (n != len) {
          printf("Sent only %d / %d bytes\n", n, len);
          return -1;
      }
      printf("Pid (%d) sended %d bytes\n", getpid(), len-4);
  }

  return 1;
}

2.3. Tmax Node

< toupper.c >
#include <stdlib.h>
#include <string.h>
#include <usrinc/atmi.h>
#include <usrinc/hlinkapi.h>

main(int argc, char *argv[])
{
  char  *sndbuf, *rcvbuf;
  long  rcvlen, sndlen;
  int ret, len;
  TPGWINFO_T gwinfo;

  strcpy(gwinfo.svc, "SVR0001");
  if (argc != 2) {
    printf("Usage: toupper string\n");
    exit(1);
  }

  if ( (ret = tmaxreadenv( "tmax.env","TMAX" )) == -1 ){
    printf( "tmax read env failed\n" );
    exit(1);
  }

  if (tpstart((TPSTART_T *)NULL) == -1){
    printf("tpstart failed\n");
    exit(1);
  }

  if ((sndbuf = (char *)tpalloc("CARRAY", NULL, 0)) == NULL) {
    printf("sendbuf alloc failed !\n");
    tpend();
    exit(1);
  }

  if ((rcvbuf = (char *)tpalloc("CARRAY", NULL, 0)) == NULL) {
    printf("recvbuf alloc failed !\n");
    tpfree((char *)sndbuf);
    tpend();
    exit(1);
  }

  memcpy(sndbuf, &gwinfo, TPGWINFO_SIZE);
  strcpy(sndbuf+TPGWINFO_SIZE, argv[1]);
  len = strlen(argv[1]);
  len += TPGWINFO_SIZE;

  if(tpcall("svcgw", sndbuf, len, &rcvbuf, &rcvlen, 0)==-1){
    printf("Can't send request to service svcgw - %d\n", tperrno);
    tpfree((char *)sndbuf);
    tpfree((char *)rcvbuf);
    tpend();
    exit(1);
  }

  printf("send data: %s\n", sndbuf+TPGWINFO_SIZE);
  printf("recv data: %s\n", rcvbuf);

  tpfree((char *)sndbuf);
  tpfree((char *)rcvbuf);
  tpend();
}

3. Client Mode Inbound Service Call

This section describes an example program that requests a remote service from Tmax through a client mode TCPGWTHR.

The example program consists of the following files.

Type File Name

Environment File

tmax.m, tcpgwthr.cfg

TCPGWTHR

usermain.c

(Refer to Server Mode Outbound Service Call for a detailed example of this file.)

Remote Node

tcpsvr2.c

Tmax Node

toupper.c

(Refer to Server Mode Inbound Service Call for a detailed example of this file.)

3.1. Environment File

< tmax.m >
*DOMAIN
res         SHMKEY = 88000,
            MINCLH = 1,
            MAXCLH = 1,
            TPORTNO = 8888

*NODE
node1       TMAXDIR = "/home/tmax",
            APPDIR = "/home/tmax/appbin"

*SVRGROUP
svg1        NODENAME = node1

*SERVER
clihdrshm   SVGNAME = svg1, MIN = 1, MAX = 1,
            SVRTYPE = CUSTOM_GATEWAY,
            CLOPT = "-- -N 10 -k 91000 -F /home/tmax/appbin/tcpgwthr.cfg"
tcpgwhdr1   SVGNAME svg1, MIN = 10, MAX = 10, SVRTYPE = CUSTOM_GATEWAY,
            CPC = 9, SCHEDULE = RR, TARGET = tcpgwhdr,
            CLOPT = "-- -k 91000 –L clihdrshm -F /home/tmax/appbin/tcpgwthr.cfg"

*SERVICE
svcgw     SVRNAME = tcpgwhdr1

3.2. Remote Node

< tcpsvr2.c >
#include  <stdio.h>
#include  <stdlib.h>
#include  <string.h>
#include  <errno.h>

#ifdef _WIN32
#include  <winsock2.h>
#include  <windows.h>
#include  <io.h>
#else
#include  <unistd.h>
#include  <netdb.h>
#include  <sys/types.h>
#include  <sys/socket.h>
#include  <sys/un.h>
#include  <netinet/in.h>
#include  <arpa/inet.h>
#endif

#define GW_PORT   9777
#define NUM_LOOP  1
#define MAX_MSG   496

#if (defined(_SOCK1) || defined(_SOCK11))
#define _LOBYTE   1
#define _HIBYTE   1
#else
#define _LOBYTE   2
#define _HIBYTE   0
#endif
#define max(a,b) ((a) > (b) ? (a) : (b))

int    listen_fd = -1;
int    work_fd;
fd_set readfds;
int    maxfd = 0;

#ifdef _WIN32
int winsock_init(void)
{
  WORD wVersionRequested;
  WSADATA wsaData;
  int err;

  wVersionRequested = MAKEWORD(_LOBYTE, _HIBYTE);
  err = WSAStartup(wVersionRequested, &wsaData);
  if (err != 0) {
     /* Tell the user that we couldn't find a usable */
     /* WinSock DLL.                                  */
     printf("0060 Winsock startup error\n");
     return -1;
  }

  /* Confirm that the WinSock DLL supports 2.0.*/
  /* Note that if the DLL supports versions greater    */
  /* than 2.0 in addition to 2.0, it will still return */
  /* 2.0 in wVersion since that is the version we      */
  /* requested.                                        */
  if (LOBYTE(wsaData.wVersion) != _LOBYTE ||
      HIBYTE(wsaData.wVersion) != _HIBYTE) {
     /* Tell the user that we couldn't find a usable */
     /* WinSock DLL.                                  */
     WSACleanup();
     printf("0061 Winsock version check error\n");
     return -1;
  }
  /* The WinSock DLL is acceptable. Proceed. */

  return 1;
}
#endif

int network_listen(int portno)
{
  int fd;
  struct sockaddr_in  serv_addr;
  int   on;

  if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
      return(-1);

  on = 1;
  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on,
           sizeof(on)) < 0) {
     printf("0062 setsockopt error: SO_REUSEADDR");
  }

  memset((char *) &serv_addr, 0, sizeof(serv_addr));
  serv_addr.sin_family      = AF_INET;
  serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  serv_addr.sin_port        = htons((unsigned short)portno);

  if (bind(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
     close(fd);
     return(-2);
  }

  if (listen(fd, 50) < 0) {
     close(fd);
     return(-3);
  }

  return(fd);
}

int network_accept(int listenfd)
{
  socklen_t len;
    int     fd, on;
  struct sockaddr_in  cli_addr;

  len = sizeof(cli_addr);
  fd = accept(listenfd, (struct sockaddr *) &cli_addr,  &len);
  if (fd < 0)
      return(-1); /* often errno=EINTR, if signal caught */

  return(fd);
}

int main(int argc, char *argv[])
{
  char  gw_addr[256];
  int gw_port, fd, i, n, len, num_loop;
  char  data[MAX_MSG], *sndbuf;

  gw_port = GW_PORT;
  if (argc == 2) {
      gw_port = atoi(argv[1]);
  }

#ifdef _WIN32
  winsock_init();
#endif

  listen_fd = network_listen(gw_port);
  if (listen_fd < 0) {
      printf("Connect to (%d) fail \n", gw_port);
      return -1;
  }

  FD_ZERO(&readfds);
  FD_SET(listen_fd, &readfds);
  maxfd = listen_fd;

  while (1) {
      errno = 0;
      n = select(maxfd + 1, &readfds, NULL, NULL, NULL);
      if (n < 0) {
         if (errno == EINTR) {     /* signal is caught */
            continue;
         } else {
            printf("0080 select error");
            return -1;
         }
      }

      if (FD_ISSET(listen_fd, &readfds)) {
         if ((fd = network_accept(listen_fd)) < 0) {
                  printf("0043 socket accept error");
            continue;
         }
               else {
            work_fd = fd;
            FD_SET(fd, &readfds);
            maxfd = max(maxfd, fd);
         }
      }

      if (FD_ISSET(work_fd, &readfds)) {
         service_process(work_fd);
         FD_CLR(work_fd, &readfds);
         close(work_fd);
      }
  }

  return 1;
}

int service_process(int fd)
{
  int    i, n, len;
  char   tmp[10];
  char   data[MAX_MSG];

  len = 4;
  n = recv(fd, data, len, 0);
  if (n != len) {
     printf("Recv error %d\n", n);
     return -1;
  }

  memcpy(tmp, data, 4);
  tmp[4] = 0x00;
  len = atoi(tmp);
  if (len <= 0) {
     printf("Pid (%d) received %d bytes\n", getpid(), n);
     return 1;
  }

  n = recv(fd, &data[4], len, 0);
  if (n != len) {
     printf("Recv error %d\n", n);
     return 1;
  }
  printf("Pid (%d) received %d bytes\n", getpid(), n);

  len = n + 4;
  for (i = 4; i < len; i++)
      data[i] = toupper(data[i]);

  n = send(fd, data, len, 0);
  if (n != len) {
     printf("Sent only %d / %d bytes\n", n, len);
     return 1;
  }
  printf("Pid (%d) sended %d bytes\n", getpid(), len-4);

  return 1;
}