Thinking Different





Winsock을 이용한 기본 에코 서버/클라이언트 구현에 필요한 간단한 CNetworkSession클래스 입니다. 공부하시는분은 참고가 되었으면 좋겠습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#pragma once
 
#include "winsock2.h"
#pragma comment(lib, "ws2_32.lib")
 
class CNetworkSession
{
protected:
    WSADATA wsaData;
    SOCKET mySocket;
    SOCKET acceptSocket;
    sockaddr_in myAddress, clntAddr;
    CNetworkSession();
    ~CNetworkSession();
public:
    int SendData(char* buffer);
    int RecvData(char* buffer, int size);
};
class Server : public CNetworkSession
{
public:
    void Start(const char *ipAddress, int port);
};
class Client : public CNetworkSession
{
public:
    void Connect(const char *ipAddress, int port);
};


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include "stdafx.h"
#include "CNetworksession.h"
 
/////////////////////////////////////////////////////////
//        Parent Class Network Basic Settings          //
/////////////////////////////////////////////////////////
CNetworkSession::CNetworkSession()
{
    if(WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR)
    {
        cerr << "WSAStartup() Error!" << endl;
        WSACleanup();
        exit(1);
    }
    mySocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(mySocket == INVALID_SOCKET)
    {
        cerr << "socket() Error!" << endl;
        WSACleanup();
        exit(1);
    }
    acceptSocket = SOCKET_ERROR;
    ZeroMemory(&myAddress, sizeof(SOCKADDR_IN));
}
CNetworkSession::~CNetworkSession()
{
    if(mySocket != INVALID_SOCKET)
    {
        closesocket(mySocket);
    }
    WSACleanup();
}
int CNetworkSession::SendData(char* buffer)
{
    return send(mySocket, buffer, strlen(buffer), 0);
}
int CNetworkSession::RecvData(char* buffer, int size)
{
    int len = recv(mySocket, buffer, size, 0);
    buffer[len] = NULL;
    return len;
}
/////////////////////////////////////////////////////////
//        Server Start (bind, listen, accept)          //
/////////////////////////////////////////////////////////
void Server::Start(const char *ipAddress, int port)
{
    myAddress.sin_family = AF_INET;
    myAddress.sin_port = htons(port);
    myAddress.sin_addr.S_un.S_addr = inet_addr(ipAddress);
 
    if(bind(mySocket, (SOCKADDR*)&myAddress, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
    {
        cerr << "bind() Error!" << endl;
        WSACleanup();
        exit(1);
    }
    if(listen(mySocket, 1) == SOCKET_ERROR)
    {
        cerr << "listen() Error!" << endl;
        WSACleanup();
        exit(1);
    }
    do {
//        int len = sizeof(clntAddr);
//        acceptSocket = accept(mySocket, (SOCKADDR*)&clntAddr, &len);
        acceptSocket = accept(mySocket, NULL, NULL);
    } while (acceptSocket == SOCKET_ERROR);
    mySocket = acceptSocket;
}
/////////////////////////////////////////////////////////
//              Client Connect() Start                 //
/////////////////////////////////////////////////////////
void Client::Connect(const char *ipAddress, int port)
{
    myAddress.sin_family = AF_INET;
    myAddress.sin_port = htons(port);
    myAddress.sin_addr.S_un.S_addr = inet_addr(ipAddress);
 
    if(connect(mySocket, (SOCKADDR*)&myAddress, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
    {
        cerr << "connect() Error!" << endl;
        WSACleanup();
        exit(1);
    }
}




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// CNetwork_test.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//
 
#include "stdafx.h"
 
enum TYPE{ServerMode, ClientMode, Quit};
 
int _tmain(int argc, _TCHAR* argv[])
{
    int nSelect = 0;
    char buffer[256];
 
    char *ipAddress = "127.0.0.1";
    int port = 9999;
 
    cout << "1 Server Mode" << endl;
    cout << "2 Client Mode" << endl;
    cout << "3 Quit" << endl << ">";
    cin >> nSelect;
 
    switch(nSelect-1)
    {
    case ServerMode:        // Server Mode
        {
            cout << "Start Server Mode !!\n";
            Server s;
            s.Start(ipAddress, port);
 
            while(s.RecvData(buffer, sizeof(buffer)) != 0)
            {
                if(strncmp(buffer, "exit", 4) == 0)
                    exit(0);
                cout << "C_MSG : " << buffer << endl;
                s.SendData(buffer);
            }
            break;
        }
    case ClientMode:        // Client Mode
        {
            cout << "Start Client Mode !!\n\n";
            Client c;
            c.Connect(ipAddress, port);
            while(1)
            {
                // input type is two.
                // 1. cin.ignore() + cin.get()
                // 2. fgets() + fflush()
                cin.ignore();
                cout << "input : ";
                cin.get(buffer, sizeof(buffer));
//2                fgets(buffer, sizeof(buffer), stdin);    input to stdin
//2                fflush(stdin);                            stdin buffer trath
                c.SendData(buffer);
                c.RecvData(buffer, sizeof(buffer));
                cout << "S_MSG : " << buffer << endl;
                if(strncmp(buffer, "exit", 4) == 0)
                    exit(0);
            }
            break;
        }
    case Quit:        // Quit
        cout << "Quit to This Program.." << endl;
        exit(0);
        break;
    default:
        cout << "Error Exit" << endl;
        break;
    }    
    return 0;
}
 



CNetworkSession에서 기본적인 소켓초기화 등을 다 해결해주고 상속된 서버/클라이언트 클래스에서 구체적인 기능만 정의하여 사용하였습니다.

프로그램의 기능은 간단히 에코기능만 넣어서 작동되도록 하였습니다. 즉 클라에서 서버로 전송된 데이터는 다시 클라이언트로 반환합니다.



tcp기반 에코server&amp;client class.zip