728x90
Client
소켓 생성 (Socket Creation)
- 클라이언트 소켓을 생성합니다. AF_INET은 IPv4, SOCK_STREAM은 TCP를 의미합니다.
SOCKET clientSocket = ::socket(AF_INET, SOCK_STREAM, 0);
서버에 연결 (Connect)
- 서버의 IP 주소와 포트 번호로 연결 요청을 보냅니다.
if (::connect(clientSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
{}
전체 코드
#include "pch.h"
#include <iostream>
#include "CorePch.h"
#include <WinSock2.h>
#include <mswsock.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
int main()
{
//윈소켓 초기화(w2_32 라이브러리 초기화)
//관련정보가 wsaData에 채워짐
WSADATA wsaData;
if (::WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
return 0;
//af : Address Family ( AF_INET = IPv4, AF_INET6 = IPv6
//type : TCP(SOCK_STREAM), UDP(SOCK_DGRAM)
//protocol : 0
//return : 성공여부
SOCKET clientSocket = ::socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket == INVALID_SOCKET)
{
int32 errCode = ::WSAGetLastError();
cout << "socket error code" << errCode << endl;
return 0;
}
//연결할 목적지 : IP주소 + PORT
SOCKADDR_IN serverAddr;//IPv4
::memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
//serverAddr.sin_addr.s_addr = ::inet_addr("127.0.0.1");
::inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr);
serverAddr.sin_port = ::htons(7777);//PORT
//htons(host to network short) Little-Endian, Big-Endian
//서버에 연결
if (::connect(clientSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
{
int32 errCode = ::WSAGetLastError();
cout << "Connect error code" << errCode << endl;
return 0;
}
//--------------------------
///연결성공
cout << "Connected To Server!" << endl;
while (true)
{
char sendBuffer[100] = "Hellow World!";
int32 resultCode = ::send(clientSocket, sendBuffer, sizeof(sendBuffer), 0);
if (resultCode == SOCKET_ERROR)
{
int32 errCode = ::WSAGetLastError();
cout << "Send error code" << errCode << endl;
return 0;
}
cout << "Send Data Len = " << sizeof(sendBuffer) << endl;
char recvBuffer[1000];
int32 recvLen = ::recv(clientSocket, recvBuffer, sizeof(recvBuffer), 0);
if (recvLen <= 0)
{
int32 errCode = ::WSAGetLastError();
cout << "Recv error code" << errCode << endl;
return 0;
}
cout << "Recv Data = " << recvBuffer << endl;
this_thread::sleep_for(1s);
}
//--------------------------
//소켓 리소스 반환
::closesocket(clientSocket);
//윈도우 소켓 종료 WSADATA호출 수만큼 정리해줘야함(권고사항)
::WSACleanup();
}
Server
소켓 생성 (Socket Creation)
- 클라이언트 소켓을 생성합니다. AF_INET은 IPv4, SOCK_STREAM은 TCP를 의미합니다.
SOCKET listenSocket = ::socket(AF_INET, SOCK_STREAM, 0);
소켓 바인드
- 소켓을 IP 주소와 포트 번호에 바인드합니다. INADDR_ANY는 모든 사용 가능한 인터페이스에서 연결을 수신하도록 설정하며, htons는 포트 번호를 네트워크 바이트 순서로 변환합니다.
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);
if (::bind(listenSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)))
{
int32 errCode = ::WSAGetLastError();
cout << "Bind error code" << errCode << endl;
return 0;
}
연결 대기(Listnener)
- 소켓을 연결 대기 상태로 만듭니다. listen 함수는 최대 10개의 대기열을 설정합니다.
if (::listen(listenSocket, 10) == SOCKET_ERROR)
연결 수락(accept)
- accept는 연결 요청이 있을 때까지 대기하며, 클라이언트와의 새 연결에 대한 소켓을 반환합니다.
SOCKET clientSocket = ::accept(listenSocket, (SOCKADDR*)&clientAddr, &addrLen);
전체코드
#include "pch.h"
#include <iostream>
#include "CorePch.h"
#include <atomic>
#include <mutex>
#include <windows.h>
#include <future>
#include "ThreadManager.h"
#include <WinSock2.h>
#include <mswsock.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
int main()
{
//윈소켓 초기화(w2_32 라이브러리 초기화)
//관련정보가 wsaData에 채워짐
WSADATA wsaData;
if (::WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
return 0;
//af : Address Family ( AF_INET = IPv4, AF_INET6 = IPv6
//type : TCP(SOCK_STREAM), UDP(SOCK_DGRAM)
//protocol : 0
//return : 성공여부
SOCKET listenSocket = ::socket(AF_INET, SOCK_STREAM, 0);
if (listenSocket == INVALID_SOCKET)
{
int32 errCode = ::WSAGetLastError();
cout << "socket error code" << errCode << endl;
return 0;
}
//나의 주소 : IP주소 + PORT
SOCKADDR_IN serverAddr;//IPv4
::memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = ::htonl(INADDR_ANY);//아이피 알아서 설정
serverAddr.sin_port = ::htons(7777);//PORT
//htons(host to network short) Little-Endian, Big-Endian
//socket과 주소 연동
if (::bind(listenSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr))== SOCKET_ERROR)
{
int32 errCode = ::WSAGetLastError();
cout << "Bind error code" << errCode << endl;
return 0;
}
//서버오픈
if (::listen(listenSocket, 10) == SOCKET_ERROR)//10은 대기열 이걸넘으면 못들어옴
{
int32 errCode = ::WSAGetLastError();
cout << "Listen error code" << errCode << endl;
return 0;
}
//--------------------------
///오픈성공
while (true)
{
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 error code" << errCode << endl;
return 0;
}
//클라이언트 입장
char ipAddress[16];
::inet_ntop(AF_INET, &clientAddr.sin_addr, ipAddress, sizeof(ipAddress));
cout << "Client Connected! IP = " << ipAddress << endl;
while (true)
{
char recvBuffer[1000];
int32 recvLen = ::recv(clientSocket, recvBuffer, sizeof(recvBuffer), 0);
if (recvLen <= 0)
{
int32 errCode = ::WSAGetLastError();
cout << "Recv error code" << errCode << endl;
return 0;
}
cout << "Recv Data = " << recvBuffer << endl;
int32 resultCode = ::send(clientSocket, recvBuffer, recvLen, 0);
if (resultCode == SOCKET_ERROR)
{
int32 errCode = ::WSAGetLastError();
cout << "Send error code" << errCode << endl;
return 0;
}
}
}
//--------------------------
//윈도우 소켓 종료 WSADATA호출 수만큼 정리해줘야함(권고사항)
::WSACleanup();
}
728x90
'VisualStudio > C++서버' 카테고리의 다른 글
[C++] Select 모델과 WASEventSelect모델 (1) | 2024.05.23 |
---|---|
[C++] setsockopt와 Socket 설정 (0) | 2024.05.23 |
[C++서버] 멀티 스레드 프로그래밍 개념 총 정리 (0) | 2023.11.22 |
[C++] 빌드폴더 위치변경 방법 & pch사용 세팅 방법 & lib 참조 방법 (0) | 2023.11.22 |
[C#서버][개념] 임계영역과 데드락 해결방법 (0) | 2022.10.26 |