1. TCP
1.1 TCP의 의미
- 인터넷상에서 데이터를 메세지의 형태로 보내기 위해 IP를 함께 사용하는 프로토콜
1.2 특징
- 연결 지향 방식
- 3-way handshaking과정을 통해 연결 설정 및 4-way handshaking을 통해 해제
- 3-way handshaking 의미
- TCP/IP프로토콜을 이용해서 통신을 하는 응용프로그램이 데이터를 전송하기 전에 먼저 정확한
전송을 보장하기 위해 상대방 컴퓨터와 사전에 세전을 수립하는 과정
- 3-way handshaking 역할
- 양쪽 모두 데이터를 전송할 준비가 되었다는 것을 보장
- 실제로 데이터 전달이 시작하기전에 한쪽이 다른 쪽이 준비되엇다는 것을 알수 있음
- 4-way handshaking 의미
- 세션을 종료하기 위해 수행되는 절차
- 흐름 제어 및 혼잡 제어
- 높은 신뢰성 보장
- UDP보다 속도 느림
1.3 TCP SERVER
- 연결을 위해 할당되는 논리적인 경로가 존재
- 데이터 경계가 없음
- 전송 순서가 보장
- 분실이 일어나면 책임지고 다시 전송 (높은 신뢰성 보장)
- 패킷에 대한 응답을 해야하므로 성능이 낮음
2 TCP SERVER Create
2.1 Winsock
- Windows Sockets API(WSA)라는 Windows API
- 인터넷 네트워크 및 소켓과 관련된 함수들을 제공
- Winsock을 사용할 수 있도록 초기화
- WSAStartup
- 첫번 째 인자는 버전을 받음
- WORD 타입이므로 하위 바이트에 주 버전 번호, 상위 바이트에 부 버전 번호가 저장
- 두번 째 인자는 윈도우 소켓 구현과 관련된 정보를 저장하는 구조체
- 성공 시 0을 반환, 실패하면 여러가지 값을 반환
- WSACleaerup
- Winsock 종료
int main()
{
WSADATA Init;
if (::WSAStartup(MAKEWORD(2, 2), &Init) != 0) return 0;
::WSACleanup();
}
2.2 Create Socket
- SOCKET(address family, type, protocol)
- 소켓 생성 실패 시 INVALID_SOCKET 반환
- address family
- AF_INET: IPv4 사용
- AF_INET6: IPv6 사용
- type
- SOCK_STREAM: 연결지향의 TCP/IP 프로토콜 사용
- SOCK_DGRAM: UDP/IP 사용
- protocol
- IPPROTO_TCP
- IPPROTO_UDP
- 0
- 0으로 설정 시 자동으로 서버에 맞는 값 설정
int main()
{
SOCKET listenSocket = ::socket(AF_INET, SOCK_STREAM, 0);
if (listenSocket == INVALID_SOCKET) return 0;
}
2.3 소켓에 대한 주소 및 포트 번호 설정
- 서버의 주소 설정 및 포트 설정
- SOCKADDR_IN 구조체 사용
- 서버는 big endian 방식을 사용
- host to network long: little endian에서 big endian 방식으로 변경
- host to network short:: big endian에서 little endian 방식으로 변경
int main()
{
SOCKADDR_IN serverAddr;
::memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = ::htonl(INADDR_ANY);
serverAddr.sin_port = ::htons(7777);
}
2.4 Socket binding
- 운영체제에 어떤 소켓이 특정 주소와 전송 계층 포트를 쓰겠다고 알려주는 절차
- 클라이언트가 내 서버로 연결 요청할 떄 상대방의 연결 요청을 받아 여러 개의 프로세스 중 적절한 프로세스로 전달
- 어떤 프로세스로 전달할지 구분하기 위해 필요한 식별자가 포트 번호
- 각 프로세스는 중복된 포트 번호를 사용X
- 수신한 패킷의 목적지 주소 및 포트가 바인딩에 사용 된 IP 주소 및 포트와 일치
- 운영체제는 해당 패킷을 바인딩 된 소켓으로 넘겨줌
int main()
{
if (::bind(listenSocket, reinterpret_cast<SOCKADDR*>(&serverAddr), sizeof(serverAddr)) == SOCKET_ERROR) return 0;
}
2.5 Server Open
- listen 함수를 사용하여 리스닝 상태에 들어간 소켓은 외부에 들어오는 클라이언트 요청을 받을 수 있게 함
int main()
{
if (::listen(listenSocket, SOMAXCONN) == SOCKET_ERROR) return 0; // SOcket MAX CONNection
}
2.5 클라이언트 접속
- 소켓을 통해 들어오는 클라이언트의 요청을 accept
- 성공하면 클라이언트의 데이터 저장
- 내부적으로 클라이언트와 통신에 사용할 수 있는 소켓을 만들고 반환
- 클라이언트의 요청이 없을 경우 accept를 호출한 스레드는 block
- Nonblocking Socket Create (TODO)
int main()
{
// listen
while (true)
{
SOCKADDR_IN clientAddr;
::memset(&serverAddr, 0, sizeof(serverAddr));
int32 addrLength = sizeof(clientAddr);
SOCKET clientSocket = ::accept(listenSocket, reinterpret_cast<SOCKADDR*>(&clientAddr), &addrLength);
if (clientSocket == INVALID_SOCKET) return 0;
}
}
2.6 클라이언트와 서버와의 통신
- recv
- 클라이언트로 부터 메시지를 받게 되면 메시지의 크기를 반환
- 데이터가 없을 경우 블로킹
int main()
{
// listen
while (true)
{
// accept
while (true)
{
char recvBuffer[MAX_BUFFER];
int32 recvLength = ::recv(clientSocket, recvBuffer, sizeof(recvBuffer), 0);
if (recvLength <= 0) return;
cout << recvBuffer << endl;
}
}
}
3. TCP Client
int main()
{
// WSA 생성
WSADATA Init;
if (::WSAStartup(MAKEWORD(2, 2), &Init) != 0) return 0;
// 소켓 생성
SOCKET clientSocket = ::socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket == INVALID_SOCKET) return 0;
// 서버 주소 및 포트 생성
SOCKADDR_IN serverAddr;
::memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
::inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr);
serverAddr.sin_port = ::htons(7777);
// 서버와 연결
if (::connect(clientSocket, reinterpret_cast<SOCKADDR*>(&serverAddr), sizeof(serverAddr)) == SOCKET_ERROR) return 0;
// 서버와의 통신
while (true)
{
char sendBuffer[MAX_BUFFER] = "TEST SERVER";
// 서버에게 메세지를 보냄
int32 sendLength = ::send(clientSocket, sendBuffer, sizeof(sendBuffer), 0);
if (sendLength <= SOCKET_ERROR) return 0;
this_thread::sleep_for(1s);
}
}
'Create Game > [Window API] Game Client & Game Server' 카테고리의 다른 글
[SEVER] Non-blocking Socket (1) | 2023.01.11 |
---|---|
[SEVER] UDP Server (0) | 2023.01.10 |
[SERVER] Memory Order (0) | 2023.01.05 |
[SERVER] Atomic (0) | 2023.01.05 |
[SERVER] Condition Variable (0) | 2023.01.03 |