1. TCP란?
TCP(Transmission Control Protocol)는 연결 지향적이고 신뢰성 있는 프로토콜이다.
특징:
- 연결 지향성 : 데이터 전송 전 연결 설정 필요
- 신뢰성 : 데이터 손실, 중복, 순서 오류 방지
- 흐름 제어 : 수신자의 처리 속도에 맞춰 전송 속도 조절
- 혼잡 제어 : 네트워크 상황에 따라 전송 속도 조절
- 전이중 통신(Full-duplex) : 양방향 동시 통신 가능
1.1. 연결 지향 통신
TCP의 연결 지향 통신은 신뢰성을 보장하기 위해 여러 방법으로 데이터를 체크한다.
- 3-way handshake: 연결 설정 시 SYN, SYN-ACK, ACK 패킷 교환
- 데이터 전송: 세그먼트 단위로 데이터 전송, 각 세그먼트에 대해 ACK 응답
- 4-way handshake: 연결 종료 시 FIN, ACK, FIN, ACK 패킷 교환
이런 특성으로 인해 TCP는 신뢰성 있는 데이터 전송을 보장하지만, UDP에 비해 오버헤드가 크다.
2. TCP 구현 순서
TCP 서버 구현 순서 :
1) 소켓 생성
2) 소켓 바인딩
3) 연결 대기(Listen)
4) 클라이언트 연결 수락(Accept)
5) 데이터 송수신
6) 연결 종료
TCP 클라이언트 구현 순서 :
1) 소켓 생성
2) 서버에 연결
3) 데이터 송수신
4) 연결 종료
3. TCP 통신의 장단점
장점 :
1) 신뢰성이 높음
- 데이터 전송 순서가 보장됨
- 패킷 손실 시 재전송 기능
- 흐름 제어와 혼잡 제어를 통한 안정적인 통신
2) 연결 지향적
- 통신 전 연결 설정 (3-way handshaking)
- 양방향 통신 가능
- 데이터 무결성 보장
3) 에러 체크
- 체크섬을 통한 데이터 오류 검출
- 손상된 패킷 재전송
단점:
1) 속도가 상대적으로 느림
- 연결 설정에 시간 소요
- 패킷 손실 시 재전송으로 인한 지연
- 오버헤드가 큼
2) 리소스 사용량이 많음
- 연결 상태 유지를 위한 메모리 사용
- 재전송을 위한 버퍼 필요
3) 실시간성 부족
- 신뢰성을 위한 각종 제어로 인한 지연
- 실시간 스트리밍에는 부적합할 수 있음
TCP 소켓 프로그래밍은 신뢰성 있는 데이터 전송이 필요한 경우에 적합하다.
웹 서버, 파일 전송 등의 애플리케이션과 게임의 중요 데이터(게임 상태, 플레이어 정보 등)에 TCP통신을 사용한다.
4. 간단한 송수신 서버
TCP 통신을 하는 송수신 서버이다.
서버
#include <iostream>
#include <string>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#define PORT 7777
using namespace std;
void HandleError(const char* cause) {
int errCode = ::WSAGetLastError();
cout << cause << " ErrorCode : " << errCode << endl;
}
int main() {
WSADATA wsaData;
if (::WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
return 1;
// 소켓 생성
SOCKET listenSocket = ::socket(AF_INET, SOCK_STREAM, 0);
if (listenSocket == INVALID_SOCKET) {
HandleError("Socket");
return 1;
}
SOCKADDR_IN serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = INADDR_ANY;
serverAddr.sin_port = htons(PORT);
// 바인드
if (::bind(listenSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
HandleError("Bind");
return 1;
}
// 리스닝
if (::listen(listenSocket, SOMAXCONN) == SOCKET_ERROR) {
HandleError("Listen");
return 1;
}
// 연결 수락
SOCKADDR_IN clientAddr;
int addrLen = sizeof(clientAddr);
SOCKET clientSocket = ::accept(listenSocket, (SOCKADDR*)&clientAddr, &addrLen);
if (clientSocket == INVALID_SOCKET) {
HandleError("Accept");
return 1;
}
cout << "Client Connected" << endl;
// 데이터 송수신
char recvBuffer[100] = { 0 };
int recvLen = ::recv(clientSocket, recvBuffer, sizeof(recvBuffer), 0);
if (recvLen <= 0) {
HandleError("Recv");
return 1;
}
cout << "Received Data : " << recvBuffer << endl;
char sendBuffer[100] = "Hello Client!";
::send(clientSocket, sendBuffer, strlen(sendBuffer), 0);
::closesocket(clientSocket);
::closesocket(listenSocket);
::WSACleanup();
system("pause"); // 콘솔 창이 바로 닫히지 않도록
}
클라이언트
#include <iostream>
#include <winsock2.h>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
#define PORT 7777
#define SERVERIP "127.0.0.1"
using namespace std;
void HandleError(const char* cause) {
int errCode = ::WSAGetLastError();
cout << cause << " ErrorCode : " << errCode << endl;
}
int main() {
WSADATA wsaData;
if (::WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
return 1;
// 소켓 생성
SOCKET clientSocket = ::socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket == INVALID_SOCKET) {
HandleError("Socket");
return 1;
}
// 서버 주소 설정
SOCKADDR_IN serverAddr;
serverAddr.sin_family = AF_INET;
::inet_pton(AF_INET, SERVERIP, &serverAddr.sin_addr); // 서버의 주소 지정
serverAddr.sin_port = htons(PORT);
// 서버 연결
if (::connect(clientSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
HandleError("Connect");
return 1;
}
cout << "Server Connected" << endl;
// 송신
char sendBuffer[100] = "Hello Server!";
::send(clientSocket, sendBuffer, strlen(sendBuffer), 0);
// 수신
char recvBuffer[100] = { 0 };
int recvLen = ::recv(clientSocket, recvBuffer, sizeof(recvBuffer), 0);
if (recvLen <= 0) {
HandleError("Recv");
return 1;
}
cout << "Received Data : " << recvBuffer << endl;
::closesocket(clientSocket);
::WSACleanup();
system("pause");
}
서버와 클라이언트가 연결되면 메시지를 한번 주고받는다.
'학습 > C++ 소켓 프로그래밍' 카테고리의 다른 글
소켓 옵션 (0) | 2024.11.08 |
---|---|
UDP 소켓 프로그래밍 (0) | 2024.10.31 |
소켓 프로그래밍 (0) | 2024.10.29 |
소켓 프로그래밍 기초 (0) | 2024.10.29 |
네트워크 프로그래밍 기초 (0) | 2024.10.22 |