开发者

OOP Sockets don't wait for accept()

we have the exercise to program a webserver in object oriented style. So we created a class for WinSockets. We wanted to loop the main part (from accept till send) to handle connections one by one (just to start up; multithreading will be implemented later).

Problem: The first time, a connection got established everything is fine, but then, the server doesn't wait for the next connection to accept. It says, it got a connection, but that descriptor throws an error, with the errornr "No Error".

main:

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;       
}


I think you're confused. You should normally have 2 sockets: 1 for accepting connections (you already have this one) and 1 for exchanging data (returned as new_fd from call to accept() in WinSocket:akzeptieren()).

In most frameworks, a big distinction is made between listener sockets and stream sockets:

// 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 );
};

So, your code should look like:

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.
}

Then, you can have:

class WinListener;
class WinStream;

And make the whole thing multi-threaded.

Note: this seems to be a requirement (assignment?), so I won't suggest that you do otherwise. However, in a real production system, this is not a good server design. You may eventually want to read about the I/O completion port, epoll and kqueue subsystems for efficient asynchronous I/O.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜