2013-03-11 5 views
1

TCP/IP 네트워크 클라이언트 통신을위한 클래스를 작성 중입니다. 클래스 헤더에 SOCKET 멤버를 만듭니다. 이 클래스에는 WSAStartup을 호출하고 버전을 확인하는 메서드가 포함되어 있습니다. 연결을 만드는 메서드는 먼저 WSAStartup을 호출 한 다음 socket() 함수를 호출하는 SOCKET 멤버를 초기화합니다. 아래 코드를 참조하십시오. 이것이 올바른지 또는 더 좋은 방법이 있는지 궁금합니다.WSAStartup()을 호출하기 전에 소켓의 인스턴스를 만들 수 있습니까?

헤더 파일 :

/*network.h*/ 
public class IPnetwork 
{ 
private: 
    WSADATA wsaData ; 
    SOCKET hSocket ; 
    sockaddr_in socketAddress ; 
    static const int SERVER_PORT = 502 ; 
    unsigned long int = serverIP ; 

public: 
    IPnetwork(char* serverIPaddress) ; 
    bool Connect() ; 
    bool Disconnect() ; 
    ~IPnetwork() ; 

private: 
    bool startWinSock() ; 
} ; 

소스 코드 :

/*network.cpp*/ 
IPnetwork::IPnetwork(char* serverIPaddress) 
{ 
    serverIP = inet_addr(serverIPaddress) ; 
} 

bool IPnetwork::Connect() 
{ 
    /* start winsock */ 
    if(!startWinSock()) 
    { 
     return false ; /* winsock problem */ 
    } 

    /* Create socket */ 
    if ((hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) 
    { 
     return false ; /* could not create socket */ 
    } 

    /* fill socket address structure */ 
    socketAddress.sin_family = AFINET ; 
    socketAddress.sin_port = htons(SERVER_PORT) ; 
    socketAddress.sin_addr.S_un.S_addr = serverIP ; 

    /* connect */ 
    if(connect(hSocket,reinterpret_cast<sockaddr*>(&socketAddress), sizeof(sockAddr))!=0) 
    { 
     return false ; /* could not connect*/ 
    } 

    return true ; 

} 

bool IPnetwork::startWinSock() 
{ 
    if(WSAStartup(MAKEWORD(REQ_WINSOCK_VER,0),&wsaData)==0) 
    { 
     /* Check if major version is at least REQ_WINSOCK_VER */ 
     if (LOBYTE(wsaData.wVersion) < REQ_WINSOCK_VER) 
     { 
      return false ; /* winsock started but version is too low */ 
     } 
     else 
     { 
      return true ; /* winsock started with right version*/ 
     } 
    } 
    else 
    { 
     return false ; /* winsock not started */ 
    } 

} 
+0

실제로 소켓을 생성하는'socket (...) '이며'SOCKET' 유형 생성자는 아닙니다. 그래서 너 괜찮아. –

답변

4

입력 SOCKET의 변수를 정의하는 방법에 대한 걱정, 때 생성자가 실행?

SOCKET은 소켓 식별자를 보유하고있는 C 호환의 평범한 데이터 통합 ​​유형이므로 문제가되지 않습니다. 그것은 대상이 아닙니다. 변수 자체와 관련된 간단한 구성이나 파괴는 없습니다.

+0

고마워, 그게 내가 걱정 한거야. – meltnot

1

당신이하고있는 일이 @Ben에 동의하는 동안 나는 개인적으로 코드의 메인 라인에서이 추함을 벗어나려고 노력할 것입니다. IMO이이 같은 헤더 뭔가,이 전역 변수를 만들 합리적인 드문 시간 중 하나입니다에

#ifndef WS_INITIATOR_INC_ 
#define WS_INITIATOR_INC_ 

#include <winsock2.h> 
#pragma comment(lib, "ws2_32.lib") 

#include <stdexcept> 

struct bad_version : public std::logic_error { 
    bad_version(std::string const &s) : logic_error(s) {} 
}; 

struct winsock { 
    static const int version = 2; 
    WSADATA wsaData; 

    winsock() { 
     WSAStartup(MAKEWORD(2, 2),&wsaData); 
     if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) 
      throw bad_version("Could not initialize WinSock 2.2"); 
    } 
    ~winsock() { 
     WSACleanup(); 
    } 
} ws_initiator; 

#endif 

이를 포함하여 main.cpp (또는 main가 포함 된 파일을주고 어떤 이름) 및 그것은 초기화/소켓 정리 (뿐만 아니라 올바른 라이브러리와 연결)를 자동화합니다.

+0

고마워, 이건 정말 더 나은 코드 디자인을 도와 줬어! – meltnot

+0

"개인적으로"winsockets를 사용하는 라이브러리에서 안전하게 사용할 수 있습니까? 주 응용 프로그램은이 라이브러리에 대해 알지 못합니다. {inprocess COM + component DLL을 생각해보십시오} – sehe

+0

@sehe : 예, 그런 상황에서는 조금 까다 롭습니다.'winsock' 객체의 인스턴스를 (예를 들어)'socket' 클래스의 멤버로 정의해야합니다 , 글로벌 변수가 아닌. 예 : http://codereview.stackexchange.com/a/46354/489 –

2

WSAStartup()을 호출해야 socket()을 호출 할 수 있습니다. 그렇지 않으면 WSANOTINITIALISED 오류가 반환됩니다.

WSAStartup() 번으로 전화를 걸 수 있습니다. WSAStartup()은 한 번만 호출하는 것이 좋지만 WinSock은 참조 횟수이므로 필요한 경우 여러 번 호출 할 수 있습니다. WSAStartup()이 성공할 때마다 WSACleanup() 번을 한 번 호출해야합니다. 그렇지 않으면 참조 수가 균형을 잃게됩니다. 예를 들어, 당신은 당신의 생성자에서 WSAStartup()을 부를 수와 소멸자에 WSACleanup() 전화 :

public class IPnetwork 
{ 
private: 
    WSADATA wsaData ; 
    bool wsaInit; 
    ... 

public: 
    IPnetwork(char* serverIPaddress) ; 
    ~IPnetwork() ; 
} ; 

합니다.

IPnetwork::IPnetwork(char* serverIPaddress) 
{ 
    wsaInit = (WSAStartup(MAKEWORD(REQ_WINSOCK_VER,0), &wsaData) == 0); 
    ... 
} 

IPnetwork::~IPnetwork() 
{ 
    if (wsaInit) WSACleanup(); 
} 

bool IPnetwork::Connect() 
{ 
    if (!wsaInit) 
     return false ; /* winsock problem */ 
    ... 
} 

일반적으로 대신 개별 싱글 톤 클래스라고 부릅니다.

+0

WSAStartup()을 생성자에서 호출 한 다음 소멸자에서 WSACleanup()을 호출합니다. –