'2025/08/23'에 해당되는 글 4건

  1. 02:00:26 pre fork read_fd write_fd

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

#define SA struct sockaddr


struct _SocketInfo
{
  int pid;
  int fd;
  int status;
};

int write_fd(int fd, void *ptr, size_t nbytes, int sendfd);
int prefork_client(int fd);
int read_fd(int fd);

int main_server(int server_sockfd,
                struct _SocketInfo *SInfo,
                struct sockaddr_in clientaddr,
                int preforknum);

int main(int argc, char **argv)
{
    char buf_in[80];
    int state;
    int clilen;
    int n,i,pid;
    int preforknum;
    int ppid;

    int sv[2];

    struct _SocketInfo *SocketArray;

    int server_sockfd, client_sockfd;
    struct sockaddr_in clientaddr, serveraddr;

    if (argc != 2)
    {
      fprintf(stderr, "Usage: %s [prefork#]\n", argv[0]);
      return 1;
    }
    preforknum = atoi(argv[1]);

    if ((server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("Error");
        return 1;
    }
    bzero(&serveraddr, sizeof(serveraddr));

    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serveraddr.sin_port = htons(8083);

    bind(server_sockfd, (SA *)&serveraddr, sizeof(serveraddr));
    if ((state = listen(server_sockfd, 5))<0)
    {
        perror("listen error: ");
        exit(0);
    }

    if(preforknum > 10)
    {
      fprintf(stderr,"Max preforknum is 10\n");
      exit(0);
    }
    ppid = getpid();

    // Socket Infomation Array
    SocketArray = (void *)malloc(sizeof(struct _SocketInfo)*preforknum);

    memset((void *)SocketArray, 0x00, sizeof(struct _SocketInfo)*preforknum);

    for (i = 0; i < preforknum; i++)
    {
      socketpair(AF_LOCAL, SOCK_STREAM, AF_LOCAL, sv);

      pid = fork();

      if (pid < 0)
      {
        perror("fork error");
        exit(0);
      }

      if (pid == 0)
      {
        dup2(sv[0], 0);
        close(sv[1]);
        close(sv[0]);
        close(server_sockfd);
        prefork_client(0);
      }
      else
      {
        close(sv[0]);
        SocketArray[i].pid    = pid;
        SocketArray[i].fd     = sv[1];
        SocketArray[i].status = 1;
      }
    }

    main_server(server_sockfd, SocketArray, clientaddr, preforknum);

}

int write_fd(int fd, void *ptr, size_t nbytes, int sendfd)
{
  struct msghdr msg;
  struct iovec iov[1];

  union {
    struct cmsghdr cm;
    char  control[CMSG_SPACE(sizeof(int))];
  } control_un;

  struct cmsghdr *cmptr;

  msg.msg_control = control_un.control;
  msg.msg_controllen = sizeof(control_un.control);

  cmptr = CMSG_FIRSTHDR(&msg);
  cmptr->cmsg_len = CMSG_LEN(sizeof(int));
  cmptr->cmsg_level = SOL_SOCKET;
  cmptr->cmsg_type = SCM_RIGHTS;

  *((int *) CMSG_DATA(cmptr)) = sendfd;

  msg.msg_name = NULL;
  msg.msg_namelen = 0;

  iov[0].iov_base = ptr;
  iov[0].iov_len = nbytes;

  msg.msg_iov = iov;
  msg.msg_iovlen = 1;

  return(sendmsg(fd, &msg, 0));

}

int read_fd(int fd)
{
  int n;
  int recvfd;
  char ptr;

  struct iovec iov[1];
  struct cmsghdr *cmptr;
  struct msghdr msg;

  union {
    struct cmsghdr cm;
    char control[CMSG_SPACE(sizeof(int))];
  } control_un;


  msg.msg_control = control_un.control;
  msg.msg_controllen = sizeof(control_un.control);

  msg.msg_name = NULL;
  msg.msg_namelen = 0;

  iov[0].iov_base = (void *)&ptr;
  iov[0].iov_len = 1;

  msg.msg_iov = iov;
  msg.msg_iovlen = 1;


  if ( (n = recvmsg(fd, &msg, 0)) <= 0)
  {
    perror("recvmsg Error");
    return -1;
  }

  cmptr = CMSG_FIRSTHDR(&msg);
  if ((cmptr == NULL))
  {
    perror("CMSG ERROR\n");
    return -1;
  }
  recvfd = *((int *) CMSG_DATA(cmptr));

  return recvfd;

}

int main_server(int server_sockfd,
      struct _SocketInfo *SocketArray,
      struct sockaddr_in clientaddr,
      int preforknum)
{
    int clilen;
    int client_sockfd;
    int i;
    char ptr;
    int n;
    int maxfd;
    fd_set readfds, allfds;
    int data;

    FD_ZERO(&readfds);
    FD_SET(server_sockfd, &readfds);

    for (i = 0; i < preforknum; i++)
    {
      FD_SET(SocketArray[i].fd, &readfds);
      maxfd = SocketArray[i].fd;
      printf("socketpair fd %d\n", maxfd);
    }

    printf("%d\n", maxfd+1);
    allfds = readfds;

    while(1)
    {
        readfds = allfds;
        clilen = sizeof(clientaddr);

        printf("select Wait\n");
        n = select(maxfd + 1, &readfds, (fd_set *)0, (fd_set *)0, NULL);
        printf("select Wait End %d\n", n);
        if (n < 0) continue;

        if (FD_ISSET(server_sockfd, &readfds))
        {
           printf("ACCEPT\n");
           if ((client_sockfd = accept(server_sockfd, (SA *)&clientaddr, (size_t *)&clilen)) ==-1)
           {
              perror("accept error:");
              close(client_sockfd);
           }
           else
           {
             for (i = 0; i < preforknum; i++)
             {
                if(SocketArray[i].status)
                {
                  printf("SocketSend pid(%d) -> %d\n", SocketArray[i].pid, client_sockfd);
                  write_fd(SocketArray[i].fd, &ptr, 1, client_sockfd);
                  SocketArray[i].status = 0;
                  close(client_sockfd);
                  break;
                }
              }
              if (i == preforknum)
              {
                fprintf(stderr, "max Client error\n");
                close(client_sockfd);
              }
           }
        }

        for (i = 0; i < preforknum; i++)
        {
          if(FD_ISSET(SocketArray[i].fd, &readfds))
          {
            printf("OK Chield Data\n");
            read(SocketArray[i].fd, (void *)&data, sizeof(data));
            printf("(%d) : Read Data %d\n", SocketArray[i].fd, data);
            if(data == 0)
            {
              SocketArray[i].status = 1;
            }
          }
        }
    }
}


int prefork_client(int fd)
{
  int n;
  char buf_in[80]={0x00,};
  int sockfd;
  int msg = 0;
  printf("Child PID %d\n", getpid());

  while(1)
  {
    sockfd = read_fd(fd);
    for(;;)
    {
      if ((n = read(sockfd, buf_in, 79)) > 0)
      {
        write(sockfd, buf_in, strlen(buf_in));
      }
      else
      {
        printf("Client Socket Close\n");
        write(fd, (void *)&msg, sizeof(msg));
        close(sockfd);
        break;
      }
      memset(buf_in, 0x00, sizeof(buf_in));
    }
  }
}

Posted by 공간사랑
,