Winsock2 소켓 프로그래밍
2019. 9. 1. 23:29ㆍPL/C++
Winsock2 라이브러리는 Window Socket API의 약자로 윈도우에서의 네트워크 프로그래밍을 지원한다. Winsock을 사용하기 위해서는 ws2_32_dll 파일을 사용 설정해야하고, WSAStartup 함수를 통해 환경 설정을 진행해야 한다
이제는 간단하게 TCP 프로토콜을 이용해서 클라이언트가 서버에게 보내면 서버가 똑같이 답하는 Echo 프로그램을 설계할 것이다. 다음과 같이 Server와 Client 프로젝트를 생성하도록 한다
그리고 위에서 말했듯이 Winsock 라이브러리를 사용하기 위해 링커에서 추가 종속성 ws2_32.lib를 추가하도록 한다
Winsock API를 처음에 setup 하는 과정을 제외하고는 일반적인 TCP 코드와 유사하다는 점을 알 수 있다
[서버]
#define _CRT_SECURE_NO_WARNINGS
#include <string>
#include <iostream>
#include <winsock2.h>
using namespace std;
void error_msg(string msg)
{
cout << "[오류발생]: " << msg << '\n';
exit(1);
}
int main(void)
{
WSADATA wsadata;
SOCKET serv_sock, cli_sock;
SOCKADDR_IN serv_addr, cli_addr;
int cli_addr_size;
int servport = 8000;
char recv_msg[256];
// winsock 2.2버전을 사용
if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0) {
error_msg("WSAStartup()");
}
serv_sock = socket(AF_INET, SOCK_STREAM, 0);
if (serv_sock == INVALID_SOCKET) {
error_msg("socket()");
}
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(servport);
if (bind(serv_sock, (SOCKADDR *)&serv_addr, sizeof(serv_addr)) == SOCKET_ERROR) {
error_msg("bind()");
}
if (listen(serv_sock, 5) == SOCKET_ERROR) {
error_msg("listen()");
}
cli_addr_size = sizeof(cli_addr);
cli_sock = accept(serv_sock, (SOCKADDR*)&cli_addr, &cli_addr_size);
if (cli_sock == INVALID_SOCKET) {
error_msg("accept()");
}
while (1) {
int len = recv(cli_sock, recv_msg, sizeof(recv_msg), 0);
// 예기치 않은 문자가 마지막에 담아졌을 수 있으므로 마지막은 NULL 문자 처리
recv_msg[len] = NULL;
cout << recv_msg << '\n';
if (strcmp(recv_msg, "[exit]") == 0) {
send(cli_sock, recv_msg, sizeof(recv_msg) - 1, 0);
cout << "서버 종료";
break;
}
send(cli_sock, recv_msg, sizeof(recv_msg) - 1, 0);
}
closesocket(serv_sock);
closesocket(cli_sock);
WSACleanup();
return 0;
}
[클라이언트]
#define _CRT_SECURE_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <string>
#include <iostream>
#include <winsock2.h>
using namespace std;
void error_msg(string msg)
{
cout << "[오류발생]: " << msg << '\n';
exit(1);
}
int main(void)
{
WSADATA wsadata;
SOCKET cli_sock;
SOCKADDR_IN serv_addr;
int servport = 8000;
char recv_msg[256];
string send_msg;
// winsock 2.2버전을 사용
if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0) {
error_msg("WSAStartup()");
}
cli_sock = socket(AF_INET, SOCK_STREAM, 0);
if (cli_sock == INVALID_SOCKET) {
error_msg("socket()");
}
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(servport);
if (connect(cli_sock, (SOCKADDR *)&serv_addr, sizeof(serv_addr)) == SOCKET_ERROR) {
error_msg("connect()");
}
while (1) {
cout << "메세지 전송 : ";
getline(cin, send_msg);
if (send_msg == "") continue;
send(cli_sock, send_msg.c_str(), send_msg.length(), 0);
int len = recv(cli_sock, recv_msg, sizeof(recv_msg), 0);
recv_msg[len] = '\0';
if (strcmp(recv_msg, "[exit]") == 0) {
break;
}
cout << "서버 메세지 : " << recv_msg << '\n';
}
closesocket(cli_sock);
WSACleanup();
return 0;
}
'PL > C++' 카테고리의 다른 글
C++에서의 string token (0) | 2019.09.02 |
---|---|
memset과 ZeroMemory (0) | 2019.09.02 |
오목 승리 판정 구현하기 (0) | 2019.09.01 |
오목 게임 화면 구성 (0) | 2019.09.01 |
C# 2차원 배열 구성해서 출력하기 (0) | 2019.09.01 |