2011-08-08 74 views
2

我们有练习以面向对象的风格编写web服务器。 所以我们为WinSockets创建了一个类。我们希望循环主要部分(从接受到发送)以逐个处理连接(仅用于启动;稍后将实施多线程)。OOP套接字不等待接受()

问题:第一次,建立连接一切正常,但服务器不会等待下一个连接接受。它说,它有一个连接,但是该描述符会引发一个错误,并显示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_fdaccept()WinSocket:akzeptieren())。

在大多数框架,大的区别监听套接字和流套接字之间进行:

// 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 port,epollkqueue子系统。