1. winsock 초기화
소켓 통신을 하기 위해서 WSADATA 객체를 만들고 WSAStartup() 함수를 통해 초기화를 시켜준다.
MAKEWORD(2, 2)는 winsock의 버전을 지정해주고 다음 인자로 만든 WSADATA 객체의 주소를 넘겨준다.
2. Socket 생성
socket()를 통해 Socket을 생성하는데 인자로 IP 주소 방식, TCP/UDP 등 소켓 방식 마지막으로 프로토콜을 설정한다.
마지막 인자에 0을 넣게 되면 프로토콜을 windows가 자동으로 선택해준다.
3. Server 주소 설정
INADDR_ANY는 특정 IP 주소가 아닌 모두 허용이다.
4. Bind = > Socket과 설정 된 정보를 묶어준다.
bind()를 통해 첫번째 인자로 생성한 Socket을 넣고 두번째로 SOCKADDR_IN으로 생성하고 정보를 입력한 객체의 주소를 SOCKADDR*로 형변환을 해서 읽을 수 있게 해준다.
마지막 인자로 생성한 SOCKADDR_IN의 사이즈를 넘겨주면 된다.
5. Listen => 대기상태로 설정
앞서 생성한 Socket은 이제 서버의 문지기가 되어 클라이언트가 접속을 시도하면 받아줄 준비를 한다.
listen()를 통해 설정한 socket을 첫번째 인자로 넣고 두 번째는 연결 요청을 받을 큐의 크기이지만 SOMAXCONN 매크로를 넣어 windows가 만들 수 있는 최대 크기를 설정할 수 있게 해준다.
6. Accept => 클라이언트 접속 허용
마지막으로 클라이언트가 접속을 시도했을 때 허용할 수 있게 accept()를 사용해 listen하고 있던 소켓에 들어온 클라이언트를 처리할 새로운 Socket에 담아주고 recv() 함수를 통해 클라이언트가 보내는 데이터를 수신하고 send()를 통해 클라이언트에게 데이터를 송신할 수 있게 된다.
이러한 에러가 뜨게 된다면
// 경고 시 이 매크로를 상단에 작성해준다.
#define _WINSOCK_DEPRECATED_NO_WARNINGS
클라이언트 코드
#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <mswsock.h>
#include <windows.h>
#pragma comment(lib, "ws2_32")
#include <iostream>
using namespace std;
#define MAX_BUFFER_SIZE 1024
int main()
{
Sleep(1);
WSADATA wsaData;
// 윈속 초기화 작업이 필수
if (::WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
cout << "초기화 실패" << endl;
return 0;
}
SOCKET clientSocket = ::socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket == INVALID_SOCKET)
{
cout << "소켓 생성 실패" << endl;
return 0;
}
SOCKADDR_IN addr = { 0 };
addr.sin_family = AF_INET;
addr.sin_port = htons(9414);
addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
if (::connect(clientSocket, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR)
{
cout << "서버 연결 에러" << endl;
closesocket(clientSocket);
WSACleanup();
return 0;
}
char buffer[MAX_BUFFER_SIZE] = { 0 };
while (true)
{
cout << "나 : ";
gets_s(buffer);
cout << endl;
if (strcmp(buffer, "EXIT") == 0)
{
break;
}
::send(clientSocket, buffer, strlen(buffer) + 1, 0);
memset(buffer, 0, sizeof(buffer));
::recv(clientSocket, buffer, sizeof(buffer), 0);
cout << "Server : " << buffer << endl;
cout << endl;
}
shutdown(clientSocket, SD_BOTH);
closesocket(clientSocket);
WSACleanup();
return 0;
}
'Socket 관련' 카테고리의 다른 글
WSAEventSelect Model (0) | 2024.06.08 |
---|---|
Select Model (0) | 2024.06.07 |
winsock2 라이브러리 추가하기 (0) | 2024.06.05 |
TCP, UDP (0) | 2024.06.02 |
Big Endian, Little Endian (0) | 2024.06.01 |