[C++] TCP 통신

2020. 12. 20. 23:51·Programming/C++
#include <iostream>
#include <WS2tcpip.h>
#include <future>

#pragma comment(lib, "ws2_32")

#define PORT 28888
#define PACKET_SIZE 36

#define SERVER_IP "127.0.0.1"
using std::cout;
using std::endl;

void server()
{
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &amp;wsaData);

    SOCKET hListen;
    hListen = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

    SOCKADDR_IN tListenAddr;
    tListenAddr.sin_family = AF_INET;
    tListenAddr.sin_port = htons(PORT);
    tListenAddr.sin_addr.s_addr = htonl(INADDR_ANY);

    bind(hListen, (SOCKADDR*)&amp;tListenAddr, sizeof(tListenAddr));
    listen(hListen, SOMAXCONN);                                                 // conenction 을 대기하는 형태로 소켓의 상태 변경.

    SOCKADDR_IN tCIntAddr;                                                      // 클라이언트 측에서 접속하면 해당 클라이언트의 정보를 저장할 구조체이다.
    int iCIntSize = sizeof(tCIntAddr);

    cout << "server accept start" << endl;
    SOCKET hClient = accept(hListen, (SOCKADDR*)&amp;tCIntAddr, &amp;iCIntSize);        // 소켓, accept 할 client 주소정보 Struct, Struct SizeOf 를 이용해
                                                                                // 접근한 Client 를 식별하고, 허용한다.
                                                                                // 해당 accept 함수는 '동기' 형태이므로
                                                                                // 클라이언트가 접근하지 않는다면 계속 유지.

    static char cBuffer[PACKET_SIZE];
    cout << "server start recv " << endl;
    if (recv(hClient, cBuffer, PACKET_SIZE, 0) == SOCKET_ERROR)
    {
        cout << "server error recv" << endl;
    }
    cout << "server end recv : " << cBuffer << endl;


    static char cMsg[] = "Server MSG";
    cout << "server start send" << endl;
    send(hClient, cMsg, strlen(cMsg), 0);
    cout << "server end send" << endl;

    closesocket(hClient);
    closesocket(hListen);

    WSACleanup();
}


void client()
{
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &amp;wsaData);

    SOCKET hSocket;
    hSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

    SOCKADDR_IN tAddr;
    tAddr.sin_family = AF_INET;
    tAddr.sin_port = htons(PORT);
    inet_pton(AF_INET, SERVER_IP, &amp;(tAddr.sin_addr.s_addr));                        // 취약한 inet_addr 함수 대신 inet_pton 함수 사용.
                                                                                    // inet_addr 은 255.255.255.255 주소 리턴값이 INADDR_NONE 타입과 같아 
                                                                                    // 구분 불가능한 문제 존재.

    char temp_;
    cout << "client input" << endl;
    std::cin >> temp_;

    connect(hSocket, (SOCKADDR*)&amp;tAddr, sizeof(tAddr));                             // Client 에서는 Bind 가 아닌 connect 함수를 이용, 
                                                                                    // SOCKET에 SOCKADDR_IN 을 매칭하게 함.
                                                                                    // 해당 코드에서는 같은 IP / Port 를 이용하였으므로
                                                                                    // 일종의 LAND Attack 과 같은 통신이 됨.
    static char cMsg[] = "client MSG";
    cout << "client start send" << endl;
    send(hSocket, cMsg, strlen(cMsg), 0);

    cout << "client end send" << endl;

    static char cBuffer[PACKET_SIZE];

    if (recv(hSocket, cBuffer, PACKET_SIZE, 0) == SOCKET_ERROR)
    {
        cout << "client recv Error" << endl;
        return;
    };
    cout << "client recv : " << cBuffer << endl;

    closesocket(hSocket);
    WSACleanup();
}

int main()
{
    auto O_server = std::async(server);
    auto O_client = std::async(client);
};

 

해당 코드는 https://kevinthegrey.tistory.com/26 을 참고하여 변형하였다.

 

 

 

 

우선, TCP, UDP 등 통신관련된 코딩은 웹에 좋은 예제들이 많이 있으므로

 

C++ #15 소켓 프로그래밍 함수

소켓 통신에 사용되는 함수들의 종류는 다음과 같다.socket(네트워크 주소 체계, 소켓 타입, 프로토콜)소켓을 생성하는 함수며 위와 같은 매개변수를 가지고 초기화 한다. 소켓 생성을 실패하면 -1

velog.io

 

*) C++를 이용한 TCP 소켓통신 구현

서버-클라이언트 환경을 만들기 위한 과정 서버  : Socket 생성 → Socket에 이름연결(bind) → 클라이언트의 연결을 기다림(listen) → 클라이언트 받아들임(accept) → 클라이언트의 명령을 받아서 적

kevinthegrey.tistory.com

이를 참고하는게 더 좋다고 생각한다. 굉장히 잘 작성한 글들이고, 덧붙일 설명이 없다

바퀴의 재생산은 필요 없다 생각하는 주의이기에....

 

 

해당 글은 필자가 간단하게 생각을 정리하기 위해 작성한 글이다.

 

 

해당 코드는 다음과 같이 동작한다.

O_server, O_client 가 작동함과 동시에

O_server 의 경우는 

 

소켓 만들고 → bind → listen 

으로 클라이언트의 connection 을 대기하는 형태로까지 만든 뒤,

cout << "server Accept Start" << endl;

메세지를 출력 후

accept() 를 통해 client 의 접속 요청이 들어올 때 까지 기다린다.

 

accept() 는 TCP 전용이며 UDP 에서는 필요하지 않다.

 

이 때 다른 thread 에서 실행된 O_client 에서는

마찬가지로

소켓 만들고 → connect (서버단이랑 (ip, port 가 같다)) → listen 한다.

 

여기까지 출력 메세지가 다음과 같다.

이 후에 메세지를 입력시

이와 같이 메세지가 뜨는데

순서대로 접근 해 보면.

O_server 의 경우는 accept 에서 대기중인 상태이므로,

O_client 에서 무언가 신호를 전송 해 주어야 한다.

 

따라서 "Send Client1 start" 가 출력되고,

그 이후에 send() 함수를 통해 Server 측으로 메세지를 전달하므로,

accept 가 풀린 server 의 "server Recv Start" 메세지가 출력되게 되며,

그리고 "server Recv End : 메세지" 가 출력되며

 

이 후 동작에서 server 가 send 로 client 에게 메세지를 전달하므로, "Server Send start" 메세지가 출력된다.

 

그 후에 Client Recv 에서 Server 가 보낸 메세지를 받게 되고

"Server Send End" 메세지를 끝으로 WSACleanup() 함수를 호출하여 코드가 종료되게 된다.

 

 

위 코드가

 

Socket Programming in PHP

What is socket programming?

medium.com

 

이와 같은 일련의 소켓 프로그래밍의 과정이다.

비록 위 이미지는 PHP 의 예제이지만, 일련의 과정은 C++ 의 그것과 크게 다를바가 없다

왜냐면 '프로토콜' 이니까

 

모든 운영체제에서 동일하게 동작하고,

모든 프로그래밍 언어에서 동일하게 수행된다.

물론 언어마다 wrap 되어있는 형태가 다를 순 있지만 근본(어셈블리) 형태는 같을것이다.

저작자표시 동일조건 (새창열림)

'Programming > C++' 카테고리의 다른 글

[C++] C# 측으로 Struct 를 UDP 로 전송  (0) 2021.04.15
[C++] OpenCV digit_svm 예제 간단 분석  (0) 2021.03.31
[C++] 람다식 mutable 의 쓰임세.  (0) 2020.12.07
[C++] push_back vs emplace_back 차이점  (2) 2020.12.07
[C++] C4819 Warning 해결 방법, 한글 깨짐 문제  (0) 2020.12.03
'Programming/C++' 카테고리의 다른 글
  • [C++] C# 측으로 Struct 를 UDP 로 전송
  • [C++] OpenCV digit_svm 예제 간단 분석
  • [C++] 람다식 mutable 의 쓰임세.
  • [C++] push_back vs emplace_back 차이점
Cyp
Cyp
  • Cyp
    Cyp Software Blog
    Cyp
  • 전체
    오늘
    어제
    • Cyp Blog (162) N
      • Artificial Intelligence (39) N
        • Article (20) N
        • Post (2)
        • Basic (14)
        • Preferences (3)
      • Cyber Security (1)
      • Programming (46)
        • C++ (21)
        • C# (19)
        • Python (2)
        • Rust (0)
        • Java (1)
      • Algorithm (17)
        • BACKJOON (15)
      • Operating System (14)
        • WSL (2)
        • Windows (1)
        • Linux (5)
        • Security (3)
      • Tools (26)
        • Docker (3)
        • DataBase (2)
        • SSH (1)
        • Doxygen (2)
        • Etc (17)
      • Miscellaneous (19)
        • Book (2)
        • Hardware (2)
        • Hevel (1)
  • 블로그 메뉴

    • Home
    • Guest Book
  • 링크

  • 공지사항

    • 블로그 업데이트 노트
    • 블로그 운영방침
  • 인기 글

  • 태그

    Bom
    utf-8 bom
    y-cruncher
    C4819
    UTF-8 without BOM
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Cyp
[C++] TCP 통신
상단으로

티스토리툴바