임시 공개 서버 코드
특징
fputs
fgets
sprintf_s를 사용함
-
솔루션 20140911_MultiThread_Server
-
프로젝트명 MutliThread_Server
-
소스코드 chat_serv_win.c
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <string.h>
-
#include <winsock2.h>
-
//#include <windows.h>
-
#include <process.h>
-
-
#define BUF_SIZE 100
-
#define MAX_CLNT 256
-
-
unsigned WINAPI HandleClnt(void *arg);
-
void SendMsg(char * msg, int len);
-
void ErrorHandling(char *msg);
-
-
int clntCnt = 0;
-
SOCKET clntSocks[MAX_CLNT];
-
HANDLE hMutex;
-
-
int main(int argc, char *argv[])
-
{
-
WSADATA wsaData;
-
SOCKET hServSock, hClntSock;
-
SOCKADDR_IN servAdr, clntAdr;
-
int clntAdrSz;
-
HANDLE hThread;
-
/*if (argc != 2) {
-
printf("Usage : <port>\n", argv[0]);
-
exit(1);
-
}*/
-
char serverPort[BUF_SIZE];
-
fputs("Input Server Port : ", stdout);
-
fgets(serverPort, BUF_SIZE, stdin);
-
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
-
ErrorHandling("WSAStartup() error!");
-
-
hMutex = CreateMutex(NULL, FALSE, NULL);
-
hServSock = socket(PF_INET, SOCK_STREAM, 0);
-
-
memset(&servAdr, 0, sizeof(servAdr));
-
servAdr.sin_family = AF_INET;
-
servAdr.sin_addr.s_addr = htonl(INADDR_ANY);
-
servAdr.sin_port = htons(atoi(serverPort));
-
-
if (bind(hServSock, (SOCKADDR*)&servAdr, sizeof(servAdr)) == SOCKET_ERROR)
-
ErrorHandling("bind() error");
-
if (listen(hServSock, 5) == SOCKET_ERROR)
-
ErrorHandling("listen() error");
-
-
while (1)
-
{
-
clntAdrSz = sizeof(clntAdr);
-
hClntSock = accept(hServSock, (SOCKADDR*)&clntAdr, &clntAdrSz);
-
-
WaitForSingleObject(hMutex, INFINITE);
-
clntSocks[clntCnt++] = hClntSock;
-
ReleaseMutex(hMutex);
-
-
hThread = (HANDLE)_beginthreadex(NULL, 0, HandleClnt, (void*)&hClntSock, 0, NULL);
-
printf("Connected client IP : %s \n", inet_ntoa(clntAdr.sin_addr));
-
}
-
closesocket(hServSock);
-
WSACleanup();
-
return 0;
-
}
-
unsigned WINAPI HandleClnt(void *arg)
-
{
-
SOCKET hClntSock = *((SOCKET*)arg);
-
int strLen = 0, i;
-
char msg[BUF_SIZE];
-
-
while ((strLen = recv(hClntSock, msg, sizeof(msg), 0)) != 0)
-
SendMsg(msg, strLen);
-
WaitForSingleObject(hMutex, INFINITE);
-
for (i = 0; i < clntCnt; i++)
-
{
-
if (hClntSock == clntSocks[i])
-
{
-
while (i++ < clntCnt - 1)
-
clntSocks[i] = clntSocks[i + 1];
-
break;
-
}
-
}
-
clntCnt--;
-
ReleaseMutex(hMutex);
-
closesocket(hClntSock);
-
return 0;
-
}
-
-
void SendMsg(char *msg, int len)
-
{
-
int i;
-
WaitForSingleObject(hMutex, INFINITE);
-
for (i = 0; i < clntCnt; i++)
-
send(clntSocks[i], msg, len, 0);
-
ReleaseMutex(hMutex);
-
}
-
-
void ErrorHandling(char* msg)
-
{
-
fputs(msg, stderr);
-
fputc('\n', stderr);
-
exit(1);
-
}
-
솔루션 20140911_MultiThread_Client
-
프로젝트명 MutliThread_Client
-
소스코드 chat_clnt_win.c
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <string.h>
-
#include <winsock2.h>
-
//#include <windows.h>
-
#include <process.h>
-
-
#define BUF_SIZE 100
-
#define NAME_SIZE 20
-
-
unsigned WINAPI SendMsg(void * arg);
-
unsigned WINAPI RecvMsg(void * arg);
-
void ErrorHandling(char * msg);
-
char name[NAME_SIZE] = "[DEFAULT]";
-
char msg[BUF_SIZE];
-
-
int main(int argc, char *argv[])
-
{
-
WSADATA wsaData;
-
SOCKET hSock;
-
SOCKADDR_IN servAdr;
-
HANDLE hSndThread, hRcvThread;
-
//if (argc != 4) {
-
// printf("Usage : %s <IP> <PORT> <name>\n", argv[0]);
-
// exit(1);
-
//}
-
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
-
ErrorHandling("WSAStartup() error!");
-
char serverIP[BUF_SIZE]; // 수동으로 입력받을 서버 IP
-
char serverPort[BUF_SIZE]; // 수동으로 입력받을 서버 Port
-
char nickname[BUF_SIZE];
-
memset(serverIP, 0, sizeof(char)* BUF_SIZE); //문자열 배열 초기화
-
memset(serverPort, 0, sizeof(char)* BUF_SIZE);
-
-
fputs("Input Server IP : ", stdout); // Stream이 연결된 곳에 뮨저열을 출력(stdout : 모니터)
-
fgets(serverIP, BUF_SIZE - 1, stdin); // Stream에서 문자열을 입력 받는다(stdin : 키보드)
-
-
fputs("Input Server Port : ", stdout);
-
fgets(serverPort, BUF_SIZE, stdin);
-
-
fputs("Input name : ", stdout);
-
fgets(nickname, BUF_SIZE - 1, stdin);
-
-
sprintf_s(name,NAME_SIZE, "[%s]", nickname);
-
-
hSock = socket(PF_INET, SOCK_STREAM, 0);
-
-
memset(&servAdr, 0, sizeof(servAdr));
-
servAdr.sin_family = AF_INET;
-
servAdr.sin_addr.s_addr = inet_addr(serverIP);
-
servAdr.sin_port = htons(atoi(serverPort));
-
-
if (connect(hSock, (SOCKADDR*)&servAdr, sizeof(servAdr)) == SOCKET_ERROR)
-
ErrorHandling("connect() error");
-
-
hSndThread = (HANDLE)_beginthreadex(NULL, 0, SendMsg, (void*)&hSock, 0, NULL);
-
hRcvThread = (HANDLE)_beginthreadex(NULL, 0, RecvMsg, (void*)&hSock, 0, NULL);
-
-
WaitForSingleObject(hSndThread, INFINITE);
-
WaitForSingleObject(hRcvThread, INFINITE);
-
-
closesocket(hSock);
-
WSACleanup();
-
return 0;
-
}
-
-
unsigned WINAPI SendMsg(void *arg)
-
{
-
SOCKET hSock = *((SOCKET*)arg);
-
char nameMsg[NAME_SIZE + BUF_SIZE];
-
while (1)
-
{
-
fgets(msg, BUF_SIZE, stdin);
-
{
-
closesocket(hSock);
-
exit(0);
-
}
-
sprintf_s(nameMsg, NAME_SIZE + BUF_SIZE, "%s %s", name, msg);
-
send(hSock, nameMsg, strlen(nameMsg), 0);
-
}
-
return 0;
-
}
-
unsigned WINAPI RecvMsg(void *arg)
-
{
-
int hSock = *((SOCKET*)arg);
-
char nameMsg[NAME_SIZE + BUF_SIZE];
-
int strLen;
-
while (1)
-
{
-
strLen = recv(hSock, nameMsg, NAME_SIZE + BUF_SIZE - 1, 0);
-
if (strLen == -1)
-
return -1;
-
nameMsg[strLen] = 0;
-
fputs(nameMsg, stdout);
-
}
-
return 0;
-
}
-
-
void ErrorHandling(char * message)
-
{
-
fputs(message, stderr);
-
fputc('\n', stderr);
-
exit(1);
-
}
-
서버 결과창
클라이언트 결과창
생각하건데... 너무간단하니까 이상함... 내가 이해를 안하고 있다고 생각함.
코드는 유연하게 짜게 됨 API 보면서...
주석이 없다는게 단점 클라는...
-
개발환경 Visual Studio 2013 for Express
-
winsock2 include와 ws2_32 .lib 연결방법
-
단일 프로젝트 속성 --> 구성속성 --> 링커 --> 입력 --> 추가종속성 --> 편집 --> ws2_32.lib 확인