WIN32API - Winsock2(TCP/IP) 이용한 간단한 C/S
#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>
#define BUFSIZE 512
// 소켓 함수 오류 출력 후 종료
void err_quit(char *msg)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER|
FORMAT_MESSAGE_FROM_SYSTEM,
NULL, WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf, 0, NULL);
MessageBox(NULL, (LPCTSTR)lpMsgBuf, msg, MB_ICONERROR);
LocalFree(lpMsgBuf);
exit(-1);
}
// 소켓 함수 오류 출력
void err_display(char *msg)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER|
FORMAT_MESSAGE_FROM_SYSTEM,
NULL, WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf, 0, NULL);
printf("[%s] %s", msg, (LPCTSTR)lpMsgBuf);
LocalFree(lpMsgBuf);
}
// 데이터 보내기
DWORD SendThread(int sock)
{
char buf[BUFSIZE + 1];
int len;
int retval;
while(1)
{
printf("\n[보낼 데이터] ");
if (fgets(buf, BUFSIZE + 1, stdin) == NULL)
break;
// '\n' 문자 제거
len = strlen(buf);
if (buf[len - 1] == '\n')
buf[len - 1] = '\0';
if (strlen(buf) == 0)
break;
// 데이터 보내기
retval = send(sock, buf, strlen(buf), 0);
if (retval == SOCKET_ERROR)
{
err_display("send()");
break;
}
printf("[TCP 클라이언트] %d바이트를 보냈습니다.\n", retval);
}
return retval;
};
void Chat(SOCKET sock,SOCKADDR_IN addr)
{
// 데이터 통신에 사용할 변수
char buf[BUFSIZE + 1];
int len=BUFSIZE;
int retval;
CreateThread(NULL,2048,(LPTHREAD_START_ROUTINE)SendThread,(LPVOID)sock,NULL,NULL);
// 클라이언트와 데이터 통신
while (1)
{
// 데이터 받기
retval = recv(sock, buf, BUFSIZE, 0);
if (retval == SOCKET_ERROR)
{
err_display("recv()");
break;
}
else if (retval == 0)
break;
// 받은 데이터 출력
buf[retval] = '\0';
printf("[TCP/%s:%d] %s\n", inet_ntoa(addr.sin_addr),
ntohs(addr.sin_port), buf);
}
// closesocket()
closesocket(sock);
}
int main(int argc, char* argv[])
{
int retval;
// 윈속 초기화
WSADATA wsa;
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
return -1;
// socket()
SOCKET listen_sock = socket(AF_INET, SOCK_STREAM, 0);
if (listen_sock == INVALID_SOCKET)
err_quit("socket()");
// bind()
SOCKADDR_IN serveraddr;
ZeroMemory(&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(9000);
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
retval = bind(listen_sock, (SOCKADDR *)&serveraddr, sizeof(serveraddr));
if (retval == SOCKET_ERROR)
err_quit("bind()");
// listen()
retval = listen(listen_sock, SOMAXCONN);
if (retval == SOCKET_ERROR)
err_quit("listen()");
// 데이터 통신에 사용할 변수
SOCKET client_sock;
SOCKADDR_IN clientaddr;
int addrlen;
char buf[BUFSIZE + 1];
while (1)
{
// accept()
addrlen = sizeof(clientaddr);
client_sock = accept(listen_sock, (SOCKADDR *)&clientaddr, &addrlen);
if (client_sock == INVALID_SOCKET)
{
err_display("accept()");
continue;
}
printf("\n[TCP 서버] 클라이언트 접속: IP 주소=%s, 포트 번호=%d\n",
inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
Chat(client_sock,clientaddr);
}
// closesocket()
closesocket(listen_sock);
// 윈속 종료
WSACleanup();
return 0;
}
> 클라이언트
#include < winsock2.h>
#include < stdlib.h>
#include < stdio.h>
#define BUFSIZE 512
// 소켓 함수 오류 출력 후 종료
void err_quit(char *msg)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER|
FORMAT_MESSAGE_FROM_SYSTEM,
NULL, WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf, 0, NULL);
MessageBox(NULL, (LPCTSTR)lpMsgBuf, msg, MB_ICONERROR);
LocalFree(lpMsgBuf);
exit(-1);
}
// 소켓 함수 오류 출력
void err_display(char *msg)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER|
FORMAT_MESSAGE_FROM_SYSTEM,
NULL, WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf, 0, NULL);
printf("[%s] %s", msg, (LPCTSTR)lpMsgBuf);
LocalFree(lpMsgBuf);
}
// 사용자 정의 데이터 수신 함수
int recvn(SOCKET s, char *buf, int len, int flags)
{
int received;
char *ptr = buf;
int left = len;
while (left > 0)
{
received = recv(s, ptr, left, flags);
if (received == SOCKET_ERROR)
return SOCKET_ERROR;
else if (received == 0)
break;
left -= received;
ptr += received;
}
return (len - left);
}
// 데이터 보내기
DWORD SendThread(int sock)
{
char buf[BUFSIZE + 1];
int len;
int retval;
while(1)
{
printf("\n[보낼 데이터] ");
if (fgets(buf, BUFSIZE + 1, stdin) == NULL)
break;
// '\n' 문자 제거
len = strlen(buf);
if (buf[len - 1] == '\n')
buf[len - 1] = '\0';
if (strlen(buf) == 0)
break;
// 데이터 보내기
retval = send(sock, buf, strlen(buf), 0);
if (retval == SOCKET_ERROR)
{
err_display("send()");
break;
}
printf("[TCP 클라이언트] %d바이트를 보냈습니다.\n", retval);
}
return retval;
};
void Chat(SOCKET sock,SOCKADDR_IN addr)
{
// 데이터 통신에 사용할 변수
char buf[BUFSIZE + 1];
int len=BUFSIZE;
int retval;
CreateThread(NULL,2048,(LPTHREAD_START_ROUTINE)SendThread,(LPVOID)sock,NULL,NULL);
// 클라이언트와 데이터 통신
while (1)
{
// 데이터 받기
retval = recv(sock, buf, BUFSIZE, 0);
if (retval == SOCKET_ERROR)
{
err_display("recv()");
break;
}
else if (retval == 0)
break;
// 받은 데이터 출력
buf[retval] = '\0';
printf("[TCP/%s:%d] %s\n", inet_ntoa(addr.sin_addr),
ntohs(addr.sin_port), buf);
}
// closesocket()
closesocket(sock);
}
int main(int argc, char* argv[])
{
int retval;
// 윈속 초기화
WSADATA wsa;
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
return -1;
// socket()
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
err_quit("socket()");
// connect()
SOCKADDR_IN serveraddr;
ZeroMemory(&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(9000);
serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
retval = connect(sock, (SOCKADDR *)&serveraddr, sizeof(serveraddr));
if (retval == SOCKET_ERROR)
err_quit("connect()");
// 윈속 종료
WSACleanup();
return 0;
}