서버/TCPIP
TCP/IP 에코서버 구현
HSH12345
2024. 10. 21. 23:41
서버
#include <iostream>
#include <string>
#include <WinSock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
#define BUFFER_SIZE 1024
#define SERVER_IP "127.0.0.1"
#define MAX_CLIENT_COUNT 5
void HandleError(const char* message)
{
cout << message << " Error: " << WSAGetLastError() << "\n";
WSACleanup();
exit(1);
}
int main(int argc, char* argv[])
{
WSADATA wsaData;
SOCKET serverSocket;
SOCKET clientSocket;
char message[BUFFER_SIZE];
int strLen;
SOCKADDR_IN serverAddr;
SOCKADDR_IN clientAddr;
int clientAddrSize;
if (argc != 2)
{
cout << "Usage: " << argv[0] << " <port>\n";
exit(1);
}
int wsaResultNum = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (wsaResultNum != 0)
{
HandleError("WSAStartup() Error");
}
serverSocket = socket(PF_INET, SOCK_STREAM, 0);
if (serverSocket == INVALID_SOCKET)
{
HandleError("socket() Error");
}
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
int ptonResultNum = inet_pton(AF_INET, SERVER_IP, &(serverAddr.sin_addr.s_addr));
if (ptonResultNum == 0)
{
HandleError("inet_pton() Error");
}
serverAddr.sin_port = htons(atoi(argv[1]));
if (serverAddr.sin_port == 0)
{
HandleError("atoi() Error");
}
int bindResultNum = bind(serverSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
if (bindResultNum == SOCKET_ERROR)
{
HandleError("bind() Error");
}
int listenResultNum = listen(serverSocket, 5);
if (listenResultNum == SOCKET_ERROR)
{
HandleError("listen() Error");
}
clientAddrSize = sizeof(clientAddr);
for (int i = 0; i < MAX_CLIENT_COUNT; i++)
{
// 클라이언트의 주소 길이는 런타임에 결정되므로 참조타입 변수 필요
clientSocket = accept(serverSocket, (SOCKADDR*)&clientAddr, &clientAddrSize);
if (clientSocket == SOCKET_ERROR)
{
HandleError("accept() Error");
}
else
{
cout << "Connected client " << i + 1 << "\n";
}
while ((strLen = recv(clientSocket, message, BUFFER_SIZE, 0)) != 0)
{
send(clientSocket, message, strLen, 0);
}
closesocket(clientSocket);
}
closesocket(serverSocket);
WSACleanup();
return 0;
}
클라이언트
#include <iostream>
#include <string>
#include <WinSock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
#define BUFFER_SIZE 1024
void HandleError(const char* message)
{
cout << message << " Error: " << WSAGetLastError() << "\n";
WSACleanup();
exit(1);
}
int main(int argc, char* argv[])
{
WSADATA wsaData;
SOCKET clinetSocket;
char message[BUFFER_SIZE];
int strLen;
SOCKADDR_IN serverAddr;
if (argc != 3)
{
cout << "Usage: " << argv[0] << " <IP> <PORT>\n";
exit(1);
}
int wsaResultNum = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (wsaResultNum != 0)
{
HandleError("WSAStartup()");
}
clinetSocket = socket(PF_INET, SOCK_STREAM, 0);
if (clinetSocket == INVALID_SOCKET)
{
HandleError("socket()");
}
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
int ptonReseultNum = inet_pton(AF_INET, argv[1], &serverAddr.sin_addr.s_addr);
if (ptonReseultNum == 0)
{
HandleError("inet_pton()");
}
serverAddr.sin_port = htons(atoi(argv[2]));
if (serverAddr.sin_port == 0)
{
HandleError("atoi() Error");
}
int connectResultNum = connect(clinetSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
if (connectResultNum == SOCKET_ERROR)
{
HandleError("connect()");
}
while (true)
{
cout << "Input message(Q to quit): ";
cin.getline(message, BUFFER_SIZE);
if (!strcmp(message, "Q") || !strcmp(message, "q"))
{
break;
}
send(clinetSocket, message, strlen(message), 0);
strLen = recv(clinetSocket, message, BUFFER_SIZE - 1, 0);
if (strLen == -1)
{
HandleError("recv()");
}
else if (strLen == 0)
{
// 서버에서 연결이 끊어진 상태를 처리
break;
}
// 널문자 추가로 문자열의 마지막 처리
message[strLen] = 0;
cout << "Message from server: " << message << "\n";
}
closesocket(clinetSocket);
WSACleanup();
return 0;
}
결과