본문 바로가기

네트워크 프로그래밍

Thread 기반 서버

#pragma comment(lib,"ws2_32.lib")
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <process.h>

#define BUFSIZE 100
#define CLNTMAXSIZE 10     //허용 클라이언트개수

DWORD WINAPI ClientConn(void *arg);
void SendMSG(char* message, int len);
void ErrorHandling(char *message);

int clntNumber=0;
SOCKET clntSocks[CLNTMAXSIZE];

int main()
{
  WSADATA wsaData;
  SOCKET servSock;
  SOCKET clntSock;

  SOCKADDR_IN servAddr;
  SOCKADDR_IN clntAddr;
  int clntAddrSize;

  HANDLE hThread;
  DWORD dwThreadID;


  if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) /* Load Winsock 2.2 DLL */
   ErrorHandling("WSAStartup() error!");


  servSock=socket(PF_INET, SOCK_STREAM, 0);  
  if(servSock == INVALID_SOCKET)
    ErrorHandling("socket() error");
 
  memset(&servAddr, 0, sizeof(servAddr));
  servAddr.sin_family=AF_INET;
  servAddr.sin_addr.s_addr=htonl(INADDR_ANY);
  servAddr.sin_port=htons(3000);

  if(bind(servSock, (SOCKADDR*) &servAddr, sizeof(servAddr))==SOCKET_ERROR)
    ErrorHandling("bind() error");

  if(listen(servSock, 5)==SOCKET_ERROR)
    ErrorHandling("listen() error");

  while(1){
   clntAddrSize=sizeof(clntAddr);
   clntSock=accept(servSock, (SOCKADDR*)&clntAddr, &clntAddrSize);
   if(clntSock==INVALID_SOCKET)
    ErrorHandling("accept() error");

   clntSocks[clntNumber++]=clntSock;
   printf("새로운 연결, 클라이언트 IP : %s \n", inet_ntoa(clntAddr.sin_addr));

   hThread = (HANDLE)CreateThread(NULL, 0, ClientConn, (void*)clntSock, 0, (unsigned *)&dwThreadID);
   if(hThread == 0) {
    ErrorHandling("쓰레드 생성 오류");
   }
  }

  WSACleanup();
  return 0;
}

DWORD WINAPI ClientConn(void *arg)
{
  SOCKET clntSock=(SOCKET)arg;
  int strLen=0;
  char message[BUFSIZE];
  int i;

  while( (strLen=recv(clntSock, message, BUFSIZE, 0)) != 0)
    SendMSG(message, strLen);

  for(i=0; i<clntNumber; i++){   // 클라이언트 연결 종료시
    if(clntSock == clntSocks[i]){
      for( ; i<clntNumber-1; i++)
    clntSocks[i]=clntSocks[i+1];
      break;
    }
  }
  clntNumber--;

  closesocket(clntSock);
  return 0;
}

void SendMSG(char* message, int len)
{
 int i;
 for(i=0; i<clntNumber; i++)
  send(clntSocks[i], message, len, 0);
}

void ErrorHandling(char *message)
{
  fputs(message, stderr);
  fputc('\n', stderr);
  exit(1);
}