2011-08-08 10 views
2

私たちは、オブジェクト指向のスタイルでWebサーバーをプログラムする練習をしています。 WinSockets用のクラスを作成しました。主要な部分(acceptからsendまで)をループして接続を1つずつ処理したい(ちょうど起動する;マルチスレッドは後で実装される)。OOPソケットはaccept()を待機しません

問題:初めて接続が確立されましたが、サーバーは次の接続が受け入れられるまで待機しません。接続がありますが、その記述子がerrornr "No Error"というエラーをスローします。

メイン:

NetInterface *socket; 
#ifdef __unix__ 
    socket = new UnixSocket(); 
#elif __WIN32__ || _MSC_VER 
    socket = new WinSocket(); 
#else 
    printf("Ihr System wird nicht Unterstützt"); 
#endif 

socket->socketInit(PORT); 

printf("server: waiting for connections...\n"); 
while(1) { // main accept() loop 
    char *their_addr = socket->akzeptieren(); 
    if(their_addr == NULL) { 
     continue; 
    } 

    printf("server: got connection from %s\n", s); 

    socket->empfangen(); 

    cout << socket->getInPacket() << endl; 
} 

WinSocket

class WinSocket : virtual public NetInterface 
{ 
private: 
    WSADATA wsaData; 
    int iResult; 

    SOCKET sockfd; 
    SOCKET new_fd; 

    struct addrinfo *servinfo; 
    struct addrinfo hints; 
    struct addrinfo *p; 

    int iSendResult; 
    string incoming; 
    int recvbuflen; 

    char s[INET6_ADDRSTRLEN]; 

    struct sockaddr_storage their_addr; // connector's address information 
    socklen_t sin_size; 

    int rv; 

public: 
    WinSocket(); 
    int socketInit(const char *port); 
    char *akzeptieren(); 
    void empfangen(); 
    void senden(string s); 
    string getInPacket(); 
    void *get_in_addr(struct sockaddr *sa); 
}; 

[....] 

char *WinSocket::akzeptieren(){ 
    sin_size = sizeof(their_addr); 
    new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size); 
    if (new_fd == INVALID_SOCKET) { 
     perror("accept"); 
     return NULL; 
    } 
    inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), s, sizeof s); 
    return s;  
} 

答えて

2

私はあなたが混乱していると思います。通常は2つのソケットが必要です。接続を受け入れるには1、データを交換するには1(new_fdはのaccept()への呼び出しから返されます)。

ほとんどのフレームワークで

が、大きな違いは、リスナーソケットとストリームソケットの間で行われますので、

// oversimplified interface. 
class Listener 
{ 
public: 
    Listener (const std::string& host, const unsigned short port); 
    Stream * accept(); 
}; 

// oversimplified interface. 
class Stream 
{ 
public: 
    const std::string peer() const; 
    size_t send (const void * data, size_t size); 
    size_t recv (  void * data, size_t size); 
}; 

、あなたのコードは次のようになります。そして、

const std::string host = "127.0.0.1"; 
const unsigned short port = 1234; 
Listener listener(host, port); 
while ((stream = listener.accept()) 
{ 
    std::cout 
     << "Connection from '" << stream->peer() << "'." 
     << std::endl; 
    stream->send("Hello, world!", 13); 
    delete stream; // close and shutdown. 
} 

、あなたが持つことができます。

class WinListener; 
class WinStream; 

そして、すべてをマルチスレッドにします。

注::これは要件(割り当てですか?)と思われるので、そうしないとお勧めしません。しかし、実際の運用システムでは、これは優れたサーバー設計ではありません。効率的な非同期I/Oのために、最終的にI/O completion portepollおよびkqueueサブシステムについて読んでみたいです。

関連する問題