Busan IT/공장내 Network2015. 8. 24. 17:45

==================================Outline====================================

select함수를 사용한 채팅 프로그램

----------------------------------------------------------------------------


select함수를 사용하여 멀티프로세스가 아닌 파일 디스크럽터 감시로 다중화 입출력을 처리한다. select함수의 단점은 채널의 수가 210승개(1024)로 제약된다는 점이다.


select함수로 감시할 파일을 지정하기 위해 FD_ZERO, FD_SET을 사용한다. 이 함수들을 사용하기 위해서 우선 fd_set 구조체를 선언해주어야 한다. FD_ZERO와 FD_SET의 인자로 생성한 fd_set구조체의 주소를 던져주어야 하기 때문이다.




fork함수를 활용하여 멀티 프로세스로 코딩하였던 채팅 프로그램을 select함수를 사용하여 만들어보자.


/*** client.c ***/

#include "smartsock.h"

int main(void)
{
  int iFd;
  struct sockaddr_in stAddr;
  int iLen;
  int iRtn;
  char cBuf[BUF_SIZE];  
  fd_set fdRead;


  /*** socket ***/
  iFd = socket(AF_INET, SOCK_STREAM, 0);
  if(-1 == iFd)
  {
    perror("socket:");
    return 100;
  }

  /*** structure setting ***/
  stAddr.sin_family = AF_INET;
  stAddr.sin_addr.s_addr = inet_addr(IP);
  stAddr.sin_port = htons(PORT);

  iLen = sizeof(struct sockaddr_in);

  /*** connect ***/
  iRtn = connect(iFd, (struct sockaddr *)&stAddr, iLen);
  if(-1 == iRtn)
  {
    perror("connect:");
    close(iFd);
    return 200;
  }

  while(1)
  {
    FD_ZERO(&fdRead);  
    FD_SET(0&fdRead);
    FD_SET(iFd, &fdRead);      
    select(iFd+1,&fdRead, 000);

    if(0 == (FD_ISSET(0&fdRead) ) )
    {
      memset(cBuf, 0, MSG_SIZE);
      iRtn = read(0, cBuf, MSG_SIZE);      
      cBuf[iRtn - 1= 0;
      write(iFd, cBuf, MSG_SIZE);
      printf("[Send MSG]: [%s]\n", cBuf);    
    }
    if(0 == (FD_ISSET(iFd, &fdRead) ))
    {
      memset(cBuf, 0, MSG_SIZE);
      iRtn = read(iFd, cBuf, MSG_SIZE);      
      printf("[Server]: [%s]\n", cBuf);    
    }
    if(0 == strncmp(cBuf, MSG_END, strlen(MSG_END)))
    {
      break;
    }    
  }

  

  /*** read & write ***/
  //memset(cBuf, 0, BUF_SIZE);
  //iRtn = read(0, cBuf, BUF_SIZE);
  

  close(iFd);
  return 0;
}

/*** server.c ***/

#include "smartsock.h"
#include <unistd.h>

int main(void)
{
  int iSock;   //소켓 함수의 반환 값을 받는 변수
  int icSock[MAX_USER];   //accept의 반환 값을 받는 변수
  int iRet;
  struct sockaddr_in stAddr;
  socklen_t uiSockLen=sizeof(struct sockaddr);
  char cBuff[BUF_SIZE];
  const char * cP;
  fd_set fdRead;
  unsigned int uiUser;
  unsigned int uiCnt;

  iSock = socket(AF_INET, SOCK_STREAM, 0);    //AF_INET = 2, 
  if(0 > iSock)
  {
    perror("socket : ");
    return -1;
  }
  // stAddr구조체에 socket연결을 위한 필수 정보 입력  setting
  bzero(&stAddr, sizeof(stAddr));            //구조체 비우기(0으로 채우기)
  stAddr.sin_family = AF_INET;               //#define AF_INET 2 /* IP protocol family. */
  stAddr.sin_addr.s_addr = inet_addr(IP);    //IP와 PORT값은 헤더파일에 정의되어 있다.
  stAddr.sin_port = htons((PORT));

  iRet = bind(iSock, (struct sockaddr *)&stAddr,sizeof(stAddr));
  if(iRet < 0)
  {
    perror("bind : ");
    close(iSock);

    return -2;
  }
  iRet = listen(iSock, 5);
  if(iRet != 0)
  {
    perror("listen : ");
    close(iSock);

    return -3;
  }
  uiUser = 0;
  while(1
  {
    FD_ZERO(0,&fdRead);
    FD_SET(0&fdRead);
    FD_SET(iSock, &fdRead);
    for(uiCnt = 0; uiCnt <= uiUsert; ++uiCnt)
    {
      FD_SET(icSock[uiCnt], &fdRead)
      
    }
    select((iSock+1+uiCnt), &fdRead, 000);

    if0 != FD_ISSET(iSock))
    {
      icSock[uiUser] = accept(iSock, (struct sockaddr *)&stAddr, &uiSockLen); //접속자의 정보가 stAddr에 입력된다.
      if(icSock[uiUser] < 0)
      {
        perror("Accept : ");
        continue;
      }
      ++uiUser;
      


    }




    if(pid ==  0)  
    {
      break;
    }
  }
  close(iSock);

  printf("Incoming Client \n");
  //cP = inet_ntoa(stAddr.sin_addr);
  printf("Client IP :%s\n", inet_ntoa(stAddr.sin_addr));
  printf("Client Port : %d\n", ntohs(stAddr.sin_port));  

  write(icSock, "Welcome :)"sizeof("Welcome :)"));

  while(1)
  {
    read(icSock, cBuff, MSG_SIZE);
    printf("[client]: [%s]\n", cBuff);

    write(icSock, cBuff, MSG_SIZE);
    if(0 == strncmp(MSG_END, cBuff, strlen(MSG_END) ) )
      break;

  }
  close(icSock);
  return 0;
}


/*** smartsock.h ***/


#ifndef __SMARTSOCK_H__
#include <sys/select.h>
#define __SMARTSOCK_H__

#include <stdio.h>
#include <string.h>
#include <strings.h>
// socket & bind & listen & accept & connect
#include <sys/types.h>
#include <sys/socket.h>

// sockaddr_in
#include <netinet/in.h>

// read & write
#include <unistd.h>

// htonl
#include <arpa/inet.h>

// errno, perror
#include <errno.h>

// open
#include <fcntl.h>
#include <sys/stat.h>

//select
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/select.h>

#define PORT      7777
#define IP        "192.168.0.173"

#define MSG_SIZE  255
#define BUF_SIZE  (MSG_SIZE+1)
#define MSG_END    "quit"

#define MAX_USER 30

#endif /* __SMARTSOCK_H__ */

client.c


server.c


smartsock.h


반응형
Posted by newind2000