본문 바로가기

카테고리 없음

임시 공개 서버 코드

특징

fputs

fgets

sprintf_s를 사용함

 

  1. 솔루션 20140911_MultiThread_Server

  2. 프로젝트명 MutliThread_Server

  3. 소스코드 chat_serv_win.c

  1. #include <stdio.h>

  2. #include <stdlib.h>

  3. #include <string.h>

  4. #include <winsock2.h>

  5. //#include <windows.h>

  6. #include <process.h>

  7.  

  8. #define BUF_SIZE 100

  9. #define MAX_CLNT 256

  10.  

  11. unsigned WINAPI HandleClnt(void *arg);

  12. void SendMsg(char * msg, int len);

  13. void ErrorHandling(char *msg);

  14.  

  15. int clntCnt = 0;

  16. SOCKET clntSocks[MAX_CLNT];

  17. HANDLE hMutex;

  18.  

  19. int main(int argc, char *argv[])

  20. {

  21.     WSADATA wsaData;

  22.     SOCKET hServSock, hClntSock;

  23.     SOCKADDR_IN servAdr, clntAdr;

  24.     int clntAdrSz;

  25.     HANDLE hThread;

  26.     /*if (argc != 2) {

  27.         printf("Usage : <port>\n", argv[0]);

  28.         exit(1);

  29.     }*/

  30.     char serverPort[BUF_SIZE];

  31.     fputs("Input Server Port : ", stdout);

  32.     fgets(serverPort, BUF_SIZE, stdin);

  33.     if (WSAStartup(MAKEWORD(22), &wsaData) != 0)

  34.         ErrorHandling("WSAStartup() error!");

  35.  

  36.     hMutex = CreateMutex(NULL, FALSE, NULL);

  37.     hServSock = socket(PF_INET, SOCK_STREAM, 0);

  38.  

  39.     memset(&servAdr, 0sizeof(servAdr));

  40.     servAdr.sin_family = AF_INET;

  41.     servAdr.sin_addr.s_addr = htonl(INADDR_ANY);

  42.     servAdr.sin_port = htons(atoi(serverPort));

  43.  

  44.     if (bind(hServSock, (SOCKADDR*)&servAdr, sizeof(servAdr)) == SOCKET_ERROR)

  45.         ErrorHandling("bind() error");

  46.     if (listen(hServSock, 5) == SOCKET_ERROR)

  47.         ErrorHandling("listen() error");

  48.  

  49.     while (1)

  50.     {

  51.         clntAdrSz = sizeof(clntAdr);

  52.         hClntSock = accept(hServSock, (SOCKADDR*)&clntAdr, &clntAdrSz);

  53.  

  54.         WaitForSingleObject(hMutex, INFINITE);

  55.         clntSocks[clntCnt++] = hClntSock;

  56.         ReleaseMutex(hMutex);

  57.  

  58.         hThread = (HANDLE)_beginthreadex(NULL, 0, HandleClnt, (void*)&hClntSock, 0, NULL);

  59.         printf("Connected client IP : %s \n", inet_ntoa(clntAdr.sin_addr));

  60.     }

  61.     closesocket(hServSock);

  62.     WSACleanup();

  63.     return 0;

  64. }

  65. unsigned WINAPI HandleClnt(void *arg)

  66. {

  67.     SOCKET hClntSock = *((SOCKET*)arg);

  68.     int strLen = 0, i;

  69.     char msg[BUF_SIZE];

  70.  

  71.     while ((strLen = recv(hClntSock, msg, sizeof(msg)0)) != 0)

  72.         SendMsg(msg, strLen);

  73.     WaitForSingleObject(hMutex, INFINITE);

  74.     for (i = 0; i < clntCnt; i++)

  75.     {

  76.         if (hClntSock == clntSocks[i])

  77.         {

  78.             while (i++ < clntCnt - 1)

  79.                 clntSocks[i] = clntSocks[i + 1];

  80.             break;

  81.         }

  82.     }

  83.     clntCnt--;

  84.     ReleaseMutex(hMutex);

  85.     closesocket(hClntSock);

  86.     return 0;

  87. }

  88.  

  89. void SendMsg(char *msg, int len)

  90. {

  91.     int i;

  92.     WaitForSingleObject(hMutex, INFINITE);

  93.     for (i = 0; i < clntCnt; i++)

  94.         send(clntSocks[i], msg, len, 0);

  95.     ReleaseMutex(hMutex);

  96. }

  97.  

  98. void ErrorHandling(char* msg)

  99. {

  100.     fputs(msg, stderr);

  101.     fputc('\n', stderr);

  102.     exit(1);

  103. }

  1. 솔루션 20140911_MultiThread_Client

  2. 프로젝트명 MutliThread_Client

  3. 소스코드 chat_clnt_win.c

  1. #include <stdio.h>

  2. #include <stdlib.h>

  3. #include <string.h>

  4. #include <winsock2.h>

  5. //#include <windows.h>

  6. #include <process.h>

  7.  

  8. #define BUF_SIZE 100

  9. #define NAME_SIZE 20

  10.  

  11. unsigned WINAPI SendMsg(void * arg);

  12. unsigned WINAPI RecvMsg(void * arg);

  13. void ErrorHandling(char * msg);

  14. char name[NAME_SIZE] = "[DEFAULT]";

  15. char msg[BUF_SIZE];

  16.  

  17. int main(int argc, char *argv[])

  18. {

  19.     WSADATA wsaData;

  20.     SOCKET hSock;

  21.     SOCKADDR_IN servAdr;

  22.     HANDLE hSndThread, hRcvThread;

  23.     //if (argc != 4) {

  24.     //  printf("Usage : %s <IP> <PORT> <name>\n", argv[0]);

  25.     //  exit(1);

  26.     //}

  27.     if (WSAStartup(MAKEWORD(22), &wsaData) != 0)

  28.         ErrorHandling("WSAStartup() error!");

  29.     char serverIP[BUF_SIZE];                    // 수동으로 입력받을 서버 IP

  30.     char serverPort[BUF_SIZE];                  // 수동으로 입력받을 서버 Port

  31.     char nickname[BUF_SIZE];

  32.     memset(serverIP, 0sizeof(char)* BUF_SIZE)//문자열 배열 초기화

  33.     memset(serverPort, 0sizeof(char)* BUF_SIZE);

  34.  

  35.     fputs("Input Server IP : ", stdout);        // Stream이 연결된 곳에 뮨저열을 출력(stdout : 모니터)

  36.     fgets(serverIP, BUF_SIZE - 1, stdin);           // Stream에서 문자열을 입력 받는다(stdin : 키보드)

  37.  

  38.     fputs("Input Server Port : ", stdout);

  39.     fgets(serverPort, BUF_SIZE, stdin);

  40.    

  41.     fputs("Input name : ", stdout);

  42.     fgets(nickname, BUF_SIZE - 1, stdin);

  43.    

  44.     sprintf_s(name,NAME_SIZE, "[%s]", nickname);

  45.  

  46.     hSock = socket(PF_INET, SOCK_STREAM, 0);

  47.  

  48.     memset(&servAdr, 0sizeof(servAdr));

  49.     servAdr.sin_family = AF_INET;

  50.     servAdr.sin_addr.s_addr = inet_addr(serverIP);

  51.     servAdr.sin_port = htons(atoi(serverPort));

  52.  

  53.     if (connect(hSock, (SOCKADDR*)&servAdr, sizeof(servAdr)) == SOCKET_ERROR)

  54.         ErrorHandling("connect() error");

  55.  

  56.     hSndThread = (HANDLE)_beginthreadex(NULL, 0, SendMsg, (void*)&hSock, 0, NULL);

  57.     hRcvThread = (HANDLE)_beginthreadex(NULL, 0, RecvMsg, (void*)&hSock, 0, NULL);

  58.  

  59.     WaitForSingleObject(hSndThread, INFINITE);

  60.     WaitForSingleObject(hRcvThread, INFINITE);

  61.  

  62.     closesocket(hSock);

  63.     WSACleanup();

  64.     return 0;

  65. }

  66.  

  67. unsigned WINAPI SendMsg(void *arg)

  68. {

  69.     SOCKET hSock = *((SOCKET*)arg);

  70.     char nameMsg[NAME_SIZE + BUF_SIZE];

  71.     while (1)

  72.     {

  73.         fgets(msg, BUF_SIZE, stdin);

  74.         if (!strcmp(msg, "q\n") || !strcmp(msg, "Q\n"))

  75.         {

  76.             closesocket(hSock);

  77.             exit(0);

  78.         }

  79.         sprintf_s(nameMsg, NAME_SIZE + BUF_SIZE, "%s %s", name, msg);

  80.         send(hSock, nameMsg, strlen(nameMsg)0);

  81.     }

  82.     return 0;

  83. }

  84. unsigned WINAPI RecvMsg(void *arg)

  85. {

  86.     int hSock = *((SOCKET*)arg);

  87.     char nameMsg[NAME_SIZE + BUF_SIZE];

  88.     int strLen;

  89.     while (1)

  90.     {

  91.         strLen = recv(hSock, nameMsg, NAME_SIZE + BUF_SIZE - 10);

  92.         if (strLen == -1)

  93.             return -1;

  94.         nameMsg[strLen] = 0;

  95.         fputs(nameMsg, stdout);

  96.     }

  97.     return 0;

  98. }

  99.  

  100. void ErrorHandling(char * message)

  101. {

  102.     fputs(message, stderr);

  103.     fputc('\n', stderr);

  104.     exit(1);

  105. }

  106.  

 

서버 결과창

 

 

클라이언트 결과창

 

 

생각하건데... 너무간단하니까 이상함... 내가 이해를 안하고 있다고 생각함.

 

코드는 유연하게 짜게 됨 API 보면서...

 

주석이 없다는게 단점 클라는...

 

  1. 개발환경 Visual Studio 2013 for Express

  2. winsock2 include와 ws2_32 .lib 연결방법

  3. 단일 프로젝트 속성 -->  구성속성 --> 링커 --> 입력 --> 추가종속성 --> 편집 --> ws2_32.lib 확인