client
#include "pch.h"
#include <iostream>
#include <WinSock2.h>
#include <MSWSock.h>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
int main()
{
//윈도우 소켓 초기화
// 관련 정보가 wsaData에 채워짐
WSADATA wsaData;
if (::WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
return 0;
// socket : address_family:(ipv4, ipv6...), type(tcp, udp), protocol / return: descriptor
SOCKET clientSocket = ::socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket == INVALID_SOCKET) {
int32 errCode = ::WSAGetLastError();
cout << "erroCode: " << errCode << endl;
return 0;
}
//연결할 목적지는?
SOCKADDR_IN serverAddr; // ipv4
::memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
::inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr); // internet presentation to network
serverAddr.sin_port = ::htons(7777); // host to network short = big_endian으로 변환해줌
if (::connect(clientSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
int32 errCode = ::WSAGetLastError();
cout << "erroCode: " << errCode << endl;
return 0;
}
//========================
// 연결 성공! 데이터 송수신 가능
cout << "Connected to Server" << endl;
while (true) {
//TODO
char sendBuffer[100] = "Hello, World!";
for (int i = 0; i < 10; ++i) {
int32 resultCode = ::send(clientSocket, sendBuffer, sizeof(sendBuffer), 0);
if (resultCode == SOCKET_ERROR) {
int32 errCode = ::WSAGetLastError();
cout << "erroCode: " << errCode << endl;
return 0;
}
cout << "Send Data! Len: " << sizeof(sendBuffer) << endl;
}
char recvBuffer[1000];
int32 recvSize = ::recv(clientSocket, recvBuffer, sizeof(recvBuffer), 0);
if (recvSize <= 0) {
int32 errCode = ::WSAGetLastError();
cout << "erroCode: " << errCode << endl;
return 0;
}
cout << "Receive Data! Len: " << recvSize << endl;
//this_thread::sleep_for(1s);
}
::closesocket(clientSocket); // 소켓 리소스 반환
::WSACleanup(); // 윈속 종료
}
Server
#include "pch.h"
#include <thread>
#include <atomic>
#include <mutex>
#include <future>
#include "CorePch.h"
#include "ThreadManager.h"
#include "RefCounting.h"
#include "Memory.h"
#include "TypeCast.h"
#include <WinSock2.h>
#include <MSWSock.h>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
int main() {
//윈도우 소켓 초기화
// 관련 정보가 wsaData에 채워짐
WSADATA wsaData;
if (::WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
return 0;
// socket : address_family:(ipv4, ipv6...), type(tcp, udp), protocol / return: descriptor
SOCKET listenSocket = ::socket(AF_INET, SOCK_STREAM, 0);
if (listenSocket == INVALID_SOCKET) {
int32 errCode = ::WSAGetLastError();
cout << "erroCode: " << errCode << endl;
return 0;
}
//연결할 목적지는?
SOCKADDR_IN serverAddr; // ipv4
::memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = ::htonl(INADDR_ANY); // 알아서 세팅해줌 유동적으로 (127.0.0.1)도 되고, 자기 ip주소도 되고
serverAddr.sin_port = ::htons(7777); // host to network short = big_endian으로 변환해줌
if (::bind(listenSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
int32 errCode = ::WSAGetLastError();
cout << "erroCode: " << errCode << endl;
return 0;
}
if (::listen(listenSocket, 10) == SOCKET_ERROR) {
int32 errCode = ::WSAGetLastError();
cout << "erroCode: " << errCode << endl;
return 0;
} // 대기열 10명까지
// 연결 성공
while (true) {
//TODO
//연결할 목적지는?
SOCKADDR_IN clientAddr; // ipv4
::memset(&clientAddr, 0, sizeof(clientAddr));
int32 addrLen = sizeof(clientAddr);
SOCKET clientSocket = ::accept(listenSocket, (SOCKADDR*)&clientAddr, &addrLen);
if (clientSocket == INVALID_SOCKET) {
int32 errCode = ::WSAGetLastError();
cout << "Accept erroCode: " << errCode << endl;
return 0;
}
//손님 입장
char ipAddress[16];
::inet_ntop(AF_INET, &clientAddr.sin_addr, ipAddress, sizeof(ipAddress));
cout << "Client Connected! IP = " << ipAddress << endl;
//TODO
while (true) {
char recvBuffer[1000];
this_thread::sleep_for(1s);
int32 recvSize = ::recv(clientSocket, recvBuffer, sizeof(recvBuffer), 0);
if (recvSize <= 0) {
int32 errCode = ::WSAGetLastError();
cout << "erroCode: " << errCode << endl;
return 0;
}
cout << recvBuffer << endl;
cout << "Receive Data! Len: " << recvSize << endl;
int32 resultCode = ::send(clientSocket, recvBuffer, recvSize, 0);
if (resultCode == SOCKET_ERROR) {
int32 errCode = ::WSAGetLastError();
cout << "erroCode: " << errCode << endl;
return 0;
}
cout << "Send Data! Len: " << recvSize << endl;
}
}
::WSACleanup(); // 윈속 종료
return 0;
}
send, recv함수는 block함수로 실제 현업에서는 사용하기 힘들어보임.
send함수는 kernel단에 send buffer에 데이터를 복사만 해도 성공
recv함수는 recv buffer에서 데이터를 복사해오면 성공
성공할 때까지 thread가 block상태이다.
'MMOServer' 카테고리의 다른 글
sockopt(C++) (0) | 2025.04.02 |
---|---|
UDP(C++) (0) | 2025.04.01 |
SocketProgramming Basic(C++) (0) | 2025.04.01 |
ObjectPooling(C++) (0) | 2025.03.29 |
MemoryPool(C++) (0) | 2025.03.28 |