Archived

This topic is now archived and is closed to further replies.

ShmeeBegek

Strange problem porting network code...

Recommended Posts

I have recently ported my server app 'vipera' to linux, and there seems to be a bug when testing on Mandrake linux. This code works the first time, but bombs out on bind() after that:
typedef struct{
        struct sockaddr_in saServer;
        int hSocket;
}iconstruct;

void *osdep_inet_waitconnect(int port)
{
        int nRet=0;
        iconstruct *ret = malloc(sizeof(iconstruct));

        int listeningSocket;

	memset(ret,0,sizeof(iconstruct));

	listeningSocket = socket(AF_INET,               // Go over TCP/IP

                                 SOCK_STREAM,           // Socket type

                                 IPPROTO_TCP);          // Protocol


        if (listeningSocket == SOCKET_ERROR)
        {
                return 0;
        }

        // Use SOCKADDR_IN to fill in address information       //      SOCKADDR_IN saServer;

        ret->saServer.sin_family = AF_INET;
        ret->saServer.sin_addr.s_addr = INADDR_ANY;             // Since this is a server, any address will do

        ret->saServer.sin_port = htons(port);
        //      // Bind the socket to our local server address  //

    nRet = bind(listeningSocket, &ret->saServer, sizeof(struct sockaddr));

        if (nRet == SOCKET_ERROR)
        {
                return 0;
        }       //      // Make the socket listen       //

        nRet = listen(listeningSocket, 10);             // 10 is the number of clients that can be queued

        if (nRet == SOCKET_ERROR)
        {
                return 0;
        }                       //      // Wait for a client    //      SOCKET theClient;

        ret->hSocket = accept(listeningSocket,
                                           NULL,                        // Address of a sockaddr structure (see below)

                                           NULL);                       // Address of a variable containing the size of sockaddr

        if (ret->hSocket == SOCKET_ERROR)
        {
                return 0;
        }
        //      // Bind the socket to our local server address  //

    nRet = bind(ret->hSocket, &ret->saServer, sizeof(struct sockaddr));

        close(listeningSocket);
        return (void*)ret;
}
This runs without problems on Windows, so there must be a difference with the Sockets API, All help is appreciated! ~SPH (Edit: fixed the Source tags -- Kylotan) [edited by - Kylotan on July 2, 2003 9:54:46 AM]

Share this post


Link to post
Share on other sites
Don''t bind() ''ret->hSocket'', it''s done implicitly for you by the stack before it is returned by the accept() call. Just start using it.

Your code is broken, the fact that it works on Windows doesn''t really matter. It''s possible that Winsock is doing some logic within the bind() call to determine if the requested socket is already bound on the requested address, or perhaps it sets the REUSEADDR flag on accept()''ed sockets (this would be simple to test). Either way, there is absolutely no reason to bind ''ret->hSocket''.

Good luck.

Share this post


Link to post
Share on other sites

Allright I stopped it from binding hSocket after accept(), but I''m still having the problem with the bind() call on the listener socket. Its strange that the first time around it works perfectly but after that it fails, maybe I''m not releasing some resource proporly?

Thanks, ~SPH

Share this post


Link to post
Share on other sites
quote:
Original post by ShmeeBegek
Its strange that the first time around it works perfectly but after that it fails, maybe I'm not releasing some resource proporly?



yeah, there's a couple of things here...
one, you might consider using the 'shutdown()' socket call. Check 'man' or MSDN for the details.
second, closing a socket doesn't mean that it's a free resource. In fact, the system will hang on to that socket for 1-5 minutes (or indefinitely) depending on the OS and the condition of the connection when you close(). When you stop your server, do `netstat -a | grep port` where 'port' is the port number you are binding to. You will see that most likely you are in a TIME_WAIT state. There are ways to prevent this from affecting your program, but you should make sure to understand them before doing it. Look at the various socket options available on your system, namely SO_REUSEADDR. That should get you started.


[edited by - fingh on July 2, 2003 6:04:33 PM]

Share this post


Link to post
Share on other sites