#1
  1. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Location
    Georgia
    Posts
    20
    Rep Power
    0

    Windows XP and Sockets Part Deux


    Ok, so I've looked at Winsock 2 and I have the winsock.h and winsock2.h libraries as well as wsock32.dll. The examples I've seen use library calls like WSAStartup et al. and I put them in my code only to have a linking errors come up on compile. I'm using gcc and I have winsock and winsock2.h included and wsock32.dll in the directory I'm working in. Is there a flag I need to add to the compile line or something I need to do with the .dll file? I'm not too bad with C but I'm a total newbie at Windows programming (and also have no idea what to do with .dll's) .

    Thanks,
    Bill
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,251
    Rep Power
    2222
    Here is what I have that works for me, albeit not on XP. I'm using the MinGW port of gcc on Win98SE.

    The command-line invocation of gcc is:

    C:\dcw\PROJECTS\WS\rtimed>gcc rtimed.c -lwsock32

    I'm using MinGW's include and library files as provided. The winsock.dll file is in the Windows system directory. The pertinent code in my example (a timserver server to provide time to my Linux laptop via rdate):
    Code:
    //#include <unistd.h>     /* for reading CLI options */
    #include <stdlib.h>     /* for atoi() */
    #include <stdio.h>      /* for printf() and fprintf() */
    #include <getopt.h>       /* for time functions */
    #include <winsock.h>    /* for socket() and bind() */
    #include <string.h>     /* for memset() */
    #include <time.h>       /* for time functions */
    
    ... 
    
    int main(int argc, char *argv[])
    {
        unsigned short serverPort;        /* Server port */
        int  protocol;                   /* IPPROTO_UDP or IPPROTO_TCP */
        SOCKET sock;                         /* Socket */
        struct sockaddr_in serverAddr;    /* Server address */
    
        WORD wVersionRequested;           /* Version of Winsock to load */
        WSADATA wsaData;                  /* Winsock implementation details */
        int opt;
    
    ... 
    
        wVersionRequested = MAKEWORD(2, 0);   /* Request Winsock v2.0 */
        if (WSAStartup(wVersionRequested, &wsaData) != 0) /* Load Winsock DLL */
        {
            fprintf(stderr,"WSAStartup() failed");
            exit(1);
        }
    
    ... 
    
        /* NOT REACHED */
    
        closesocket(sock);
        WSACleanup();  /* Cleanup Winsock */
    
    }
    
    
    
    
    void DieWithError(char *errorMessage)
    {
    //    perror(errorMessage);
        fprintf(stderr,"%s: %d\n", errorMessage, WSAGetLastError());
        exit(1);
    }
    Those are the only consessions I make to Winsock; the rest of the program is identical to UNIX/Linux sockets code.

    Now, I have not tried it yet on Win2k -- my wife and son are usually on it so I don't get to use it for development work. I'll give it a try using Visual C++6, since I don't have gcc installed on it.

    Please note that MinGW does not support getopt, so I created my own library file and added it to the default libraries.

    I've ZIP'ed and attached the source code of rtimed, getopt header and .a library file, and a .bat file to compile the program. See if it will compile on your system.

    EDIT:
    Oops! I just gave you some compiled executable in the form of that library file, libopt.a. OK, don't use it, but you'll need to make a few changes to the source file:

    Comment out or remove these lines. Usage will default to tcp port 37.
    Code:
        while ((opt = getopt(argc,argv,"uth")) != -1)
        {
            switch(opt)
            {
                case 'u':
                    protocol = IPPROTO_UDP;
                    break;
                case 't':
                    protocol = IPPROTO_TCP;
                    break;
                case 'h':
                    printf("Usage: rtimed [-uth] [port]\n");
                    printf("    -h : display usage\n");
                    printf("    -u : use udp\n");
                    printf("    -t : use tcp\n");
                    printf("  Defaults:\n");
                    printf("    tcp protocol\n");
                    printf("    port 37 (timserver)\n");
                    exit(0);
            }
        }
        
        if (optind < argc)    
            serverPort = atoi(argv[optind]);
    Comment out or remove these two lines:
    #include <getopt.h> /* for time functions */
    int opt;

    Compile with this line command:
    gcc -o rtimed rtimed.c -lwsock32

    There, that should be safe now.
    Attached Files
    Last edited by dwise1_aol; June 23rd, 2003 at 07:59 PM.
  4. #3
  5. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,251
    Rep Power
    2222
    OK, I compiled it fine on my Win2K and it ran and set the time on my Linux laptop client.

    The thing with DLLs in Windows is that they are loaded and linked upon the program's request when the program is being executed. During compile-time, all you need is the header file so that the exported functions and data can be known.

    In the case of Winsock, you have both a static library and a DLL. For gcc, the static library is libwsock32.a, which needs to be linked in when you compile/make. Then the WSAStartup() function call when the program runs is what loads the DLL in.

    Again, the sample command line for gcc would be (again using my sample program):
    gcc -o rtimed rtimed.c -lwsock32
  6. #4
  7. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Location
    Georgia
    Posts
    20
    Rep Power
    0

    My Code


    The code is kind of a mess, but here's what I have. At the moment I'm just trying to connect the client to the server when both are running on the localhost. My server seems to work fine, but I'll include the code (and I apologize for the code dump)

    Here are the relevant parts of the server code:
    void main(int argc, char argv[]){

    int r_value, addrlen;
    unsigned short portno; /* Server port */
    int protocol; /* IPPROTO_UDP or IPPROTO_TCP */
    SOCKET mySocket, newSocket; /* Socket */
    struct sockaddr_in servaddr,fromaddr; /* Server and client address*/
    WORD wVersionRequested; /* Version of Winsock to load */
    WSADATA wsaData; /* Winsock implementation details */
    bzero((char *) &servaddr, sizeof(servaddr));


    wVersionRequested = MAKEWORD(2, 0); /* Request Winsock v2.0 */
    if (WSAStartup(wVersionRequested, &wsaData) != 0) /* Load Winsock D
    {
    fprintf(stderr,"WSAStartup() failed");
    exit(1);
    }

    if( (mySocket = socket(AF_INET,SOCK_STREAM,0)) <0){
    printf("Error opening socket\n");
    exit(1);
    }
    portno=2303;
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(portno);
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    r_value = bind(mySocket,(struct sockaddr *)&servaddr,sizeof(servaddr));
    if(r_value<0){
    printf("Error binding to port!\n");
    closesocket(mySocket);
    WSACleanup(); /* Cleanup Winsock */
    exit(1);
    }
    printf("bind successful, listening on port\n");
    r_value = listen(mySocket,5);
    if(r_value<0){
    printf("Error listening on port!\n");
    closesocket(mySocket);
    WSACleanup(); /* Cleanup Winsock */
    exit(1);
    }
    printf("Listening\n");
    addrlen= sizeof(fromaddr);
    while(1){
    /*Accept connections from clients*/
    printf("About to accept\n");
    newSocket= accept( mySocket, (struct sockaddr*)&fromaddr,\
    &addrlen);
    printf("Accepted\n");
    if(newSocket<0){
    printf("Error accepting connections\n");
    closesocket(mySocket);
    WSACleanup(); /* Cleanup Winsock */
    exit(1);
    }
    /*process the clients*/
    else{
    process_Clients(newSocket);
    }
    }
    }

    The server starts up fine and appears to be waiting for accept to return.

    And here are the relevant parts of the client code, where I hope the problem resides:

    int connectToServer(){

    unsigned short portno; /* Server port */
    int protocol; /* IPPROTO_UDP or IPPROTO_TCP */
    SOCKET mySocket; /* Socket */
    struct sockaddr_in dest_address; /* Server address */

    WORD wVersionRequested; /* Version of Winsock to load */
    WSADATA wsaData; /* Winsock implementation details */

    wVersionRequested = MAKEWORD(2, 0); /* Request Winsock v2.0 */
    if (WSAStartup(wVersionRequested, &wsaData) != 0) /* Load Winsock DLL*/

    {
    printf("WSAStartup() failed");
    exit(1);
    }


    if ((mySocket = socket(PF_INET, SOCK_STREAM, 0)) < 0){
    printf("Socket Creation Failed\n");
    exit(1);
    }
    else{
    printf("Socket Creation Successful\n");
    }
    portno = 2303;
    dest_address.sin_port = htons(portno);
    dest_address.sin_addr.s_addr = htonl(inet_addr(IP_ADDRESS));
    dest_address.sin_family = AF_INET;
    if(connect(mySocket,(struct sockaddr *)&dest_address,
    sizeof(dest_address))<0){
    printf("Can't Connect!\n");
    exit(1);
    }
    else {
    return mySocket;
    }
    }

    So again, sorry for dumping it here but I've been staring at it for so long I can't figure it out.

    Thanks,
    Bill
  8. #5
  9. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,251
    Rep Power
    2222
    I'll take a look at it during lunch.

    When you include a code listing, you should use the code tags to keep the indentation. Just before the listing, type [ code ] and after the listing type [ /code ] (without the extra spaces, then I needed to include to defeat the formatting). Do a quote on a message to see the general syntax of tags on these fora.

    BTW, I just discovered a neat trick to get around somebody not using the code tags. Just start a quote response on that message and in the edit window the code still has its original indentation. Actually, this discovery is the main reason for this response.
  10. #6
  11. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,251
    Rep Power
    2222

    Re: My Code


    Originally posted by ueberbill
    The code is kind of a mess, but here's what I have. At the moment I'm just trying to connect the client to the server when both are running on the localhost. My server seems to work fine, but I'll include the code (and I apologize for the code dump)
    ...

    So again, sorry for dumping it here but I've been staring at it for so long I can't figure it out.

    Thanks,
    Bill
    What kind of trouble are you having? At the top of the thread the problem was getting the program to link using Winsock. I assume that that problem has been solved now. What is the error indication now? You may have mentioned it in a previous thread, but my inter-thread memory isn't that good -- I must not be getting enough cookies (HTML/Javascript joke).
  12. #7
  13. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Location
    Georgia
    Posts
    20
    Rep Power
    0
    My apologies for not being clear and not using the code tags (I'm the kind of guy they just posted that New Users Read This post for). Indeed my linking errors have gone away, the problem is that the client won't connect to the server when both are running on the localhost (not to even MENTION a remote one). The server appears to start up fine and gets through until it's holding in the accept but the client prints out the "Can't Connect!" line and exits after taking a few seconds (I'm assuming that it times out, but I'm not sure exactly how to diagnose the error).

    Thanks,
    Bill
  14. #8
  15. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,251
    Rep Power
    2222
    Found something:
    The function, inet_addr, converts a dotted-decimal IP address string to its binary representation already in network byte order. Not only do you not need to run it through htonl(), but doing so would screw it up. You cannot connect to the server because you are addressing the wrong host (I wonder who 1.0.0.127 is).

    So in your client, the line:
    dest_address.sin_addr.s_addr = htonl(inet_addr(IP_ADDRESS));

    should instead read:
    dest_address.sin_addr.s_addr = inet_addr(IP_ADDRESS);

    In the server, the defined constant INADDR_ANY does still need to have its byte order converted, so the server should be right.

    See if that does the job.

    PS
    You mean I was supposed to read "New Users Read This"? But I'm a programmer; we never read the manual first. :D
  16. #9
  17. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Location
    Georgia
    Posts
    20
    Rep Power
    0
    Perfect! That nailed it. I really appreciate the help.

    Bill
  18. #10
  19. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,251
    Rep Power
    2222
    I fell for a similar trick once. I forgot to use htons on the port number. The server and client that I wrote worked just fine with each other (both had the same error in them), but my client couldn't talk to another server -- failed to connect. Had me going for a day or two, as I recall. I only spotted it by comparing my code with sample code.

IMN logo majestic logo threadwatch logo seochat tools logo