[네트워크 프로그래밍] 1. 소켓 프로그래밍 기초

유기태·2023년 11월 23일
0
// 서버
#include<WinSock2.h>
#include<mswsock.h>
#include<ws2tcpip.h>
#pragma comment(lib,"ws2_32.lib")

int main()
{
	// 전체적인 흐름
	// winsock 초기화 -> socket 생성 -> 내 서버 주소 정의 -> bind
	// -> listen -> accept
	WSADATA wsaData;
	int32 err;
	err = ::WSAStartup(MAKEWORD(2, 2), &wsaData);

	if (err != 0)
	{
		cout << "Winsock Initialize Failed\n" << err << " :  error exists";
		return 0;
	}

	// 상담을 받아주는 안내원( 회사의 공식 대표 번호)
	// 말 그대로 처음 clinetsocket을 받아주는 소켓이라 보면됨
	SOCKET listenSocket = ::socket(AF_INET, SOCK_STREAM, 0);
	if (listenSocket == INVALID_SOCKET)
	{
		err = ::WSAGetLastError();
		cout << "Socket ErrorCode : " << err << endl;
		return 0;
	}

	// 회사의 대표 주소지 설정
	SOCKADDR_IN serverAddr;
	::memset(&serverAddr, 0, sizeof(serverAddr));
	serverAddr.sin_family = AF_INET;
	// 니가 알아서 골라줘 네트워크 카드가 여러개일 경우 해결
	serverAddr.sin_addr.s_addr = ::htonl(INADDR_ANY);
	serverAddr.sin_port = ::htonl(7777);

	// 안내원 폰 개통! 식당의 대표 번호
	err = ::bind(listenSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
	if (err == SOCKET_ERROR)
	{
		err = ::WSAGetLastError();
		cout << "Bind ErrorCode : " << err << endl;
		return 0;
	}

	// 영업 시작
	// parameter
	// 1. socket
	// 2. backlog(대기열의 최대 한도)
	err = ::listen(listenSocket, 15);
	if (err == SOCKET_ERROR)
	{
		err = ::WSAGetLastError();
		cout << "Listen ErrorCode : " << err << endl;
		return 0;
	}

	//---------------

	while (true)
	{
		SOCKADDR_IN clientAddr;
		::memset(&clientAddr, 0, sizeof(clientAddr));
		int32 addrLen = sizeof(clientAddr);
		// accept 뒤의 두개 파라미터는 생략 가능
		SOCKET clientSocket = ::accept(listenSocket, (SOCKADDR*)&clientAddr, &addrLen);
		if (clientSocket == INVALID_SOCKET)
		{
			err = ::WSAGetLastError();
			cout << "Accept ErrorCode : " << err << endl;
			return 0;
		}
	}

	//---------------

	return 0;
}
// 클라이언트
#include "pch.h"
#include <CorePch.h>

#include <WinSock2.h>
#include <mswsock.h>
#include <ws2tcpip.h>
#pragma comment(lib,"ws2_32.lib")

int main()
{

	// 전체적인 흐름
	// wsastartup(초기화) -> socket 준비 -> socket addr 준비 -> connect -> wsacleanup()
	WSADATA wsData;
	// winsock을 사용할 준비가 되었다(ws2_32 라이브러리 초기화)
	// parameter
	// 1. winsock 버전
	// 2. winsock 관련 정보가 wsData에 채워짐
	// 성공시 return 값이 0임
	int err = ::WSAStartup(MAKEWORD(2, 2), &wsData);
	if (err != 0)
	{
		cout << "WSAStartUp initialize failed\n" << err << " : error exists";
		return 0;
	}

	// 전화를 걸 전화기 생성 ( 이 socket을 이용해 데이터 전송 )
	// parameter
	// 1. 주소체계(IPv4 / IPv6) -> 네트워크 주소 할당의 문제로 새로운 주소 체계 편입
	// AF_INET(IPv4 주소 체계)
	// AF_INET(IPv6 주소 체계)
	// 2. socket type (TCP / UDP)
	// SOCK_STREAM(TCP활용) / SOCK_DGRAM(UDP활용)
	// 신뢰성 / 비신뢰성(패킷 소실의 위험성이 있음)
	// 왠만하면 TCP 사용
	// 3. protocol은 0으로 입력(default값)
	// return : descriptor를 return 함
	SOCKET clientSocket = ::socket(AF_INET, SOCK_STREAM, 0);

	if (clientSocket == INVALID_SOCKET)
	{
		int32 errCode = ::WSAGetLastError();
		cout << "Socket ErrorCode : " << errCode << endl;
		return 0;
	}

	// 식당 번호 입력
	SOCKADDR_IN serverAddr; // IPv4 용
	// SOCKADDR_IN6 IPv6용
	::memset(&serverAddr, 0, sizeof(serverAddr));
	// IPv4용이기때문에 항상 AF_INET을 설정해야함
	serverAddr.sin_family = AF_INET;
	// 주소체계는 1바이트씩 끊어서 사용 2^8 -> 256까지
	// inet_addr은 너무 구식
	// serverAddr.sin_addr.S_un.S_addr = ::inet_addr("192.168.123.100");
	// 127.0.0.1 루프백 주소(내 자신의 컴퓨터 ip)
	// 나중에는 DNS를 활용
	::inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr);
	// 포트 번호 연결할 목적지는? ( IP주소 + Port )-> IP아파트 Port 동
	// 일부 번호는 예약 되어있기 때문에 port는 이왕이면 10000번대를 넘어서 등록하면 좋다
	// htons
	// host to network short
	// network to host short 
	// Little-Endian vs Big-Endian
	// ex) 0x12345678 4바이트 정수
	// [0x78][0x56][0x34][0x12] <- little
	// [0x12][0x34][0x56][0x78] <- big
	// 요즘 대부분은 리틀엔디안 사용(intel corp.)
	// network에서는 빅엔디안을 사용함
	serverAddr.sin_port = ::htons(7777);

	// 그 주소로 전화를 걸기!
	// parameter
	// 1. socket
	// 2. socketaddr 
	// -> 전화를 걸 대상 ( type casting 하는 이유는 주소 체계가 다 다르기 때문에 공통되게 만들어줌)
	err = ::connect(clientSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
	if (err == SOCKET_ERROR)
	{
		int32 errCode = ::WSAGetLastError();
		cout << "Connect ErrCode : " << errCode << endl;
		return 0;
	}

	// 연결 성공 ! 이제부터 데이터 송수신 가능!

	cout << "Connected To Server!" << endl;

	while (true)
	{
		// TODO
	}
	
	// 소켓 리소스 반환
	::closesocket(clientSocket);
	 
	// winsock 해제
	::WSACleanup();
}
profile
게임프로그래머 지망!

0개의 댓글