#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2003
    Posts
    41
    Rep Power
    12

    Socket Programming in C help!!!


    Hi there,

    I have posted this message, but I really do need some help here!
    Thank you!

    I am supposed to build a proxy that will talk to both my client and my server. My server will be a PostGreSql program running on port 5432.

    I can do upto the part where my proxy will wait and listen to all the incoming connections. However, when the client requests for password from the proxy, which means that the proxy will have to pass the info to the PSql server, then get the message back and pass it to the client, then I have problem.

    How do I know how to pass message back and fort between my proxy and the PSql server?

    Any help will be appriciated.

    Geekoid
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,162
    Rep Power
    2222
    I'm not sure what problem you're having, but I think I have an idea.

    You are working two sockets at the same time: one is the server socket that the client connects to and the other is the client socket that connects to the PostGreSql server. Normally, sockets block, so your single-thread app is stuck trying to receive from one socket and unable to service the other.

    There are ways around that:
    1. Make it a multi-threaded application and service the two sockets in separate threads -- can be daunting for the uninitiated.
    2. Make the sockets non-blocking -- more complicated to code.
    3. Use select().

    Here's an example of select() that I used in MiM, my "man in the middle" project described earlier (from my notes, so the code may not compile):
    Code:
    void ProcessTCP(unsigned short ListenPort,char *servIP,unsigned short ServPort)
    {
        int servSock;                    /* Socket descriptor for server */
        int clntSock;                    /* Socket descriptor for client */
        int sock;                        /* Socket descriptor */
        struct sockaddr_in ServAddr; /* Echo server address */
    
        fd_set sockSet;                  /* Set of socket descriptors for select() */
        long timeout;                    /* Timeout value given on command-line */
        long timeout_ms;                 /* Timeout value given on command-line */
        struct timeval selTimeout;       /* Timeout for select() */
        int running = 1;                 /* 1 if server should be running; 0 otherwise */
    
        servSock = CreateTCPServerSocket(ListenPort);
    
        clntSock = AcceptTCPConnection(servSock);
    
        /* Create a reliable, stream socket using TCP */
        /* this socket will connect to the server */
        if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
            DieWithError("socket() failed");
    
        /* Construct the server address structure */
        memset(&ServAddr, 0, sizeof(ServAddr));     /* Zero out structure */
        ServAddr.sin_family      = AF_INET;             /* Internet address family */
        ServAddr.sin_addr.s_addr = inet_addr(servIP);   /* Server IP address */
        ServAddr.sin_port        = htons(ServPort); /* Server port */
        /* Establish the connection to the echo server */
        if (connect(sock, (struct sockaddr *) &ServAddr, sizeof(ServAddr)) < 0)
            DieWithError("connect() failed");
    
        timeout = 0;
        timeout_ms = 100000;
    
        while (running)
        {
            /* Zero socket descriptor vector and set for server sockets */
            /* This must be reset every time select() is called */
            FD_ZERO(&sockSet);
            FD_SET(sock, &sockSet);
            FD_SET(clntSock, &sockSet);
    
            /* Timeout specification */
            /* This must be reset every time select() is called */
            selTimeout.tv_sec = timeout;       /* timeout (secs.) */
            selTimeout.tv_usec = timeout_ms;   /* microseconds */
    
            /* Suspend program until descriptor is ready or timeout */
            /* The first parameter to select() is ignored in Winsock */
            if (select(0, &sockSet, NULL, NULL, NULL) > 0)
            {
                  if (FD_ISSET(sock, &sockSet))
                  {
                         HandleTCPMsg(sock,clntSock,"Server");
    //                will read data from the server and pass it to the client
                  }
    
                  if (FD_ISSET(clntSock, &sockSet))
                  {
                         HandleTCPMsg(clntSock,sock,"Client");
    //                will read data from the client and pass it to the server
                  }
             }
    
        }
        closesocket(sock);
    }
    The idea behind using select() here is that it will test whether there is anything to read from a socket before you commit to calling the revc() function.

    Does this address your problem?

    BTW, the code is primarily for UNIX, but it will work for Windows as well, especially the use of select(). Though you might have to make a few minor changes (eg, declare the sockets to be of type SOCKET).
    Last edited by dwise1_aol; June 5th, 2003 at 10:30 AM.
  4. #3
  5. not a fan of fascism (n00b)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Feb 2003
    Location
    ct
    Posts
    2,756
    Rep Power
    95
    just too add a bit too what dwise said as im unsure what OS/API your doing this with. if your using win32, there is the function:
    WSAAsyncSelect(), which will send a WM_SOCKET message to your WndProc and let you handle all incoming messages when they come without having to manually poll the sockets. if you'd like the code for this method i can post it when i get home?

IMN logo majestic logo threadwatch logo seochat tools logo