TCP 특징
TCP와 UDP
TCPTransmission Control Protocol의 약자로 전송을 제어하는 포로토콜이라는 뜻으로 인터넷상에서 데이터를 메시지 형태로 보내기 위해 IP와 함께 사용하는 프로토콜이다.주로 TCP와 IP를 함께 사용하며,
hoyeot.tistory.com
서버는 특정 IP와 포트에서 수신을 위해 소켓을 생성
클라이언트 서버에 연결을 요청(Connect)
서버는 연결을 수락(Accept), 데이터 수신 상태(Listen)
클라이언트가 데이터를 송신하면 서버는 이 데이터를 읽고 다시 클라이언트에게 송신
소스 코드
// server
#include <WinSock2.h> // Windows 소켓 헤더 파일
#include <WS2tcpip.h> // IP 주소 변환 함수 헤더 파일
#include <iostream>
#define IP "127.0.0.1" // IP
#define PORT 8000 // PORT
#define BUFF_SIZE 50 // 버퍼 크기
using namespace std;
int main()
{
WSAData wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET hServerSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // TCP 소켓 생성
if (hServerSock == INVALID_SOCKET)
{
cout << "Socket Create Error" << endl;
exit(0);
}
// 서버 주소
SOCKADDR_IN serverAddr = { 0, };
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT);
inet_pton(AF_INET, IP, &serverAddr.sin_addr);
// 바인딩
if (bind(hServerSock, (LPSOCKADDR)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
{
cout << "Bind Error" << WSAGetLastError() << endl;
closesocket(hServerSock);
WSACleanup();
exit(0);
}
// 리스닝
if (listen(hServerSock, SOMAXCONN) == SOCKET_ERROR)
{
cout << "Listen Error" << WSAGetLastError() << endl;
closesocket(hServerSock);
WSACleanup();
exit(0);
}
cout << "TCP SERVER START" << endl;
// 클라이언트 연결 대기
SOCKET hClientSock;
SOCKADDR_IN clientAddr;
int clientADDrSize = sizeof(clientAddr);
hClientSock = accept(hServerSock, (SOCKADDR*)&clientAddr, &clientADDrSize);
if (hClientSock == INVALID_SOCKET)
{
cout << "Accept Error" << WSAGetLastError() << endl;
closesocket(hServerSock);
WSACleanup();
exit(0);
}
cout << "Client Connected" << endl;
char message[BUFF_SIZE];
int recvLength;
// 데이터 송수신 루프
while ((recvLength = recv(hClientSock, message, BUFF_SIZE, 0)) > 0)
{
message[recvLength] = '\0'; // 문자열 종료
cout << "Received : " << message << endl;
send(hClientSock, message, recvLength, 0); // 에코
}
// 소켓 종료
closesocket(hClientSock);
closesocket(hServerSock);
WSACleanup();
return 0;
}
// client
#include <WinSock2.h> // Windows 소켓 헤더 파일
#include <WS2tcpip.h> // IP 주소 변환 함수 헤더 파일
#include <iostream>
#define IP "127.0.0.1" // IP
#define PORT 8000 // PORT
#define BUFF_SIZE 50 // 버퍼 크기
using namespace std;
int main()
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
// TCP 소켓 생성
SOCKET hClientSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (hClientSock == INVALID_SOCKET)
{
cout << "Socket Error" << WSAGetLastError() << endl;
WSACleanup();
exit(0);
}
// 서버 주소 설정
SOCKADDR_IN servAddr = { 0, };
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(PORT);
inet_pton(AF_INET, IP, &servAddr.sin_addr);
// 서버와 연결
if (connect(hClientSock, (LPSOCKADDR)&servAddr, sizeof(servAddr)) == SOCKET_ERROR)
{
cout << "Connect Error : " << WSAGetLastError() << endl;
closesocket(hClientSock);
WSACleanup();
exit(0);
}
cout << "Server Connected!" << endl;
char message[BUFF_SIZE]; // 송수신을 위한 버퍼
int sendLength = 0; // 송신된 데이터의 길이
// 메인 루프
while (1)
{
cout << "Input Text" << endl;
fgets(message, sizeof(message), stdin); // 입력을 버퍼에 저장
if (!strcmp(message, "exit\n") || !strcmp(message, "EXIT\n")) break;
sendLength = send(hClientSock, message, strlen(message), 0); // 서버로 데이터 송신
int recvLength = recv(hClientSock, message, BUFF_SIZE, 0); // 서버로부터 데이터 수신
message[recvLength] = 0;
cout << "Receive : " << message << endl;
}
// 종료
closesocket(hClientSock);
WSACleanup();
return 0;
}