01.03

신승빈·2023년 1월 3일
0

KGCA 수업

목록 보기
88/128

Socket Programming


// inet_addr()함수는 현재 Deprecated.
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h>
#pragma comment (lib, "Ws2_32.lib")

int main()
{
    WSADATA wsa;
    // WSAStartup : Winsock DLL을 시작하는 함수
    // MAKEWORD WORD 생성 Macro
    if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
    {
        return 0;
    }

	// TCP
    //SOCKET sock1 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    // UDP
    //SOCKET sock2 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    // 마지막 옵션을 0으로 설정함으로써 TCP/UDP 모두 사용 가능
    SOCKET sock3 = socket(AF_INET, SOCK_STREAM, 0);

    // client
    SOCKADDR_IN sa;
    sa.sin_family = AF_INET;	// IP 주소 체계. PF_INET도 있음, 그 외 IPX, UNIT 등 존재
    sa.sin_addr.s_addr = inet_addr("192.168.0.12");	// string을 byte로 변환하는 함수. Deprecated 됨
    sa.sin_port = htons(10000);	// host to network short. 엔디안 정렬 함수. ntohs, ntohl, htonl 등이 있음
    int iRet = connect(sock3, (sockaddr*)&sa, sizeof(sa));
    if (iRet == SOCKET_ERROR)
    {
        return 1;
    }    
    
    // Server
    SOCKADDR_IN sa;
    sa.sin_family = AF_INET;   
    sa.sin_addr.s_addr = htonl(INADDR_ANY);	// 지정된 Port로부터 연결 요청이 오는 모든 Address
    sa.sin_port = htons(10000);
    int iRet = bind(sock3, (sockaddr*)&sa, sizeof(sa));
    if (iRet == SOCKET_ERROR)
    {
        return 1;
    }
    iRet = listen(sock3, SOMAXCONN);	// 최대 연결, 운영체제별로 값이 다른듯
    if (iRet == SOCKET_ERROR)
    {
        return 1;
    }

    u_long iMode = TRUE;
    // Socket의 Blocking-non Blocking mode 설정
    // FIONBIO : Blocking-Non Blocking설정 시 필요하다고는 하는데 의미는 모르겠음
    // mode값을 통해 Block-Non Block설정 가능
    ioctlsocket(sock3, FIONBIO, &iMode);   
    while (1)
    {      
        char szSendMsg[256] = { 0, };
        printf("%s", "send---->");
        fgets(szSendMsg, 256, stdin);

        int iSendBytes = send(sock3, szSendMsg, strlen(szSendMsg), 0);
        if (iSendBytes == SOCKET_ERROR)
        {
        //	WSAEWOULDBLOCK : Non-Blocking Socket의 명령이 즉각 수행될 수 없을 때 설정되는 값
        // 공식 문서에 따르면 '이는 모드로 인해 호출이 즉시 반환되지 않았다면 차단되었을 것임을 나타냅니다.'
            if (WSAGetLastError() != WSAEWOULDBLOCK)
            {
                closesocket(sock3);
                return 1;
            }
            continue;
        }      
    
        char szRecvMsg[256] = { 0, }; 
        int iRecvBytes = recv(sock3, szRecvMsg, 256, 0);
        if (iRecvBytes == SOCKET_ERROR)
        {
            if (WSAGetLastError() != WSAEWOULDBLOCK)
            {
                closesocket(sock3);
                return 1;
            }
            continue;
        }     
    }
       
    // Socket은 File과 마찬가지로 open-close를 꼭 수행해야 함
    closesocket(sock3);
    WSACleanup();
}

Blocking-Non Blocking Socket

Blocking-Non Blocking은 동기화와는 다른 개념
비동기화는 함수가 끝나지 않았음에도 함수 밖으로 나오는 것을 의미
Non Blocking은 Background에서 함수의 연산이 돌지 않음

Reference : https://yoopaark.tistory.com/6

WSAEWOULDBLOCK

Non-Blocking Socket의 명령이 즉각 수행될 수 없을 때 설정되는 값
공식 문서에 따르면 '이는 모드로 인해 호출이 즉시 반환되지 않았다면 차단되었을 것임을 나타냅니다.'

Reference : https://learn.microsoft.com/ko-kr/cpp/mfc/windows-sockets-blocking?view=msvc-170

Windows OS에서의 send(), recv()

Windows OS에서는 Socket마다 RW Buffer를 제공하며 이 RW Buffer에 데이터가 저장되었느냐 여부에 따라 send, recv의 반환

profile
이상을 길잡이 삼아 로망을 추구합니다.

0개의 댓글