/*
 * chat_server_win.c
 * Written by SW. YOON
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <process.h>

#define BUFSIZE 100

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

int clntNumber=0;
SOCKET clntSocks[10];
HANDLE hMutex;

int main(int argc, char **argv)
{
  WSADATA wsaData;
  SOCKET servSock;
  SOCKET clntSock;

  SOCKADDR_IN servAddr;
  SOCKADDR_IN clntAddr;
  int clntAddrSize;

  HANDLE hThread;
  HANDLE hThread2;

  DWORD dwThreadID;

  if(argc!=2){
    printf("Usage : %s <port>\n", argv[0]);
    exit(1);
  }
  if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) /* Load Winsock 2.2 DLL */
   ErrorHandling("WSAStartup() error!");

  hMutex=CreateMutex(NULL, FALSE, NULL);
  if(hMutex==NULL){
   ErrorHandling("CreateMutex() 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(atoi(argv[1]));

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

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

 hThread2 = (HANDLE)_beginthreadex(NULL, 0, input, NULL, 0, (unsigned *)&dwThreadID);

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

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

   hThread = (HANDLE)_beginthreadex(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)) != -1)
    SendMSG(message, strLen);

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

  closesocket(clntSock);
  return 0;
}
DWORD WINAPI input(void *arg)
{
  SOCKET clntSock=(SOCKET)arg;
  int strLen=0;
  char message[BUFSIZE-9];
  char message1[BUFSIZE];
  while(1){
   fgets(message, BUFSIZE,stdin);
   sprintf(message1, "[server] %s", message);
   SendMSG(message1, BUFSIZE);


  }
 
  return 0;
}

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

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

------------------------------------------------------------------------------
/*
 * chat_client_win.c
 * Written by SW. YOON
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <process.h>

#define BUFSIZE 100
#define NAMESIZE 20

DWORD WINAPI SendMSG(void *arg);
DWORD WINAPI RecvMSG(void *arg);
void ErrorHandling(char *message);

char name[NAMESIZE]="[Default]";
char message[BUFSIZE];

int main(int argc, char **argv)
{
  WSADATA wsaData;
  SOCKET sock;
  SOCKADDR_IN servAddr;
 
  HANDLE hThread1, hThread2;
  DWORD dwThreadID1, dwThreadID2;

  if(argc!=4){
    printf("Usage : %s <IP> <port> <name>\n", argv[0]);
    exit(1);
  }
  if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) /* Load Winsock 2.2 DLL */
   ErrorHandling("WSAStartup() error!");
  sprintf(name, "[%s]", argv[3]);

  sock=socket(PF_INET, SOCK_STREAM, 0);
  if(sock == INVALID_SOCKET)
    ErrorHandling("socket() error");

  memset(&servAddr, 0, sizeof(servAddr));
  servAddr.sin_family=AF_INET;
  servAddr.sin_addr.s_addr=inet_addr(argv[1]);
  servAddr.sin_port=htons(atoi(argv[2]));
 
  if(connect(sock, (SOCKADDR*)&servAddr, sizeof(servAddr))==SOCKET_ERROR)
   ErrorHandling("connect() error");
 
  hThread1 = (HANDLE)_beginthreadex(NULL, 0, SendMSG, (void*)sock, 0, (unsigned *)&dwThreadID1);
  hThread2 = (HANDLE)_beginthreadex(NULL, 0, RecvMSG, (void*)sock, 0, (unsigned *)&dwThreadID2);
  if(hThread1==0 || hThread2==0) {
   ErrorHandling("쓰레드 생성 오류");
  }
 
  WaitForSingleObject(hThread1, INFINITE);
  WaitForSingleObject(hThread2, INFINITE);
 
  closesocket(sock);
  return 0;
}

DWORD WINAPI SendMSG(void *arg) // 메시지 전송 쓰레드 실행 함수
{
   SOCKET sock = (SOCKET)arg;
   char nameMessage[NAMESIZE+BUFSIZE];
   while(1) {
      fgets(message, BUFSIZE, stdin);
      sprintf(nameMessage,"%s %s", name, message);
      if(!strcmp(message,"q\n")) {  // 'q' 입력시 종료
         closesocket(sock);
         exit(0);  
      }
      send(sock, nameMessage, strlen(nameMessage), 0);
   }
}

DWORD WINAPI RecvMSG(void *arg) /* 메시지 수신 쓰레드 실행 함수 */
{
  SOCKET sock = (SOCKET)arg;
  char nameMessage[NAMESIZE+BUFSIZE];
  int strLen;
  while(1){
    strLen = recv(sock, nameMessage, NAMESIZE+BUFSIZE-1, 0);
 if(strLen==-1) return 1;
 
    nameMessage[strLen]=0;
    fputs(nameMessage, stdout);
  }
}

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


신고

'Dreaming Box' 카테고리의 다른 글

Australia: in Brisbane  (0) 2008.11.23
과제1. SQL문 작성  (0) 2008.11.20
Table 생성, 삽입  (0) 2008.11.18
네트워크: 멀티쓰레드_서버구현  (0) 2008.11.12
지역변수, 전역변수  (0) 2008.11.08
memset(), memcpy()  (0) 2008.11.08
cvReleaseCapture : CvCapture 구조체의 메모리를 반환  (0) 2008.11.04
CvvImage : MFC용 이미지 클래스  (0) 2008.11.04
Posted by 온라인브랜드디렉터 강정은

▲ TOP으로 이동