| Tenouk.com | Winsock Program Example 9 | Main | Winsock Program Example 11 >| Site Index | Download |


 

WINSOCK 2

WINDOWS SOCKET: PROGRAM EXAMPLES PART 10

 

 

 

Winsock Tutorial

 

Winsock: Story 1

Winsock: Story 2

Winsock: Story 3

Winsock: Example 1

Winsock: Example 2

Winsock: Example 3

Winsock: Example 4

Winsock: Example 5

Winsock: Example 6

Winsock: Example 7

Winsock: Example 8

Winsock: Example 9

Winsock: Example 10

Winsock: Example 11

Winsock: Example 12

Winsock: Reference 1

Winsock: Reference 2

Winsock: Reference 3

Winsock: Reference 4

My Training Period:          hours

 

Note:

This is a continuation from previous Module.

Machine’s OS is standalone Windows Xp Pro with SP2 except whenever mentioned.  Compiler used was Visual C++ 2003 .Net 1.1. Beware the codes that span more than one line.  Program examples have been tested for Non Destructive Test :o).  All information compiled for Windows 2000 (NT5.0) above and...

 

  1. Related functions, structures and macros used in the program examples have been dumped at Winsock structure & function 1 and Winsock structure & function 2.
  2. Other related and required information (if any) not available in no. 2 can be found at MSDN & Visual C++ online reference.

 

Abilities

 

         Able to understand the advanced networking of the TCP/IP.

         Able to understand Winsock implementation and operations through the APIs and program examples.

         Able to gather, understand and use the Winsock functions, structures and macros in your programs.

         Able to build programs that use Microsoft C/Standard C programming language and Winsock APIs.

 

addrinfo

 

Item

Description

Structure

addrinfo.

Info

Used by the getaddrinfo() function to hold host address information.

Definition

typedef struct addrinfo {
  int ai_flags;
  int ai_family;
  int ai_socktype;
  int ai_protocol;
  size_t ai_addrlen;
  char* ai_canonname;
  struct sockaddr* ai_addr;
  struct addrinfo* ai_next;

} addrinfo;

Members

ai_flags

Flags that indicate options used in the getaddrinfo() function. See AI_PASSIVE, AI_CANONNAME, and AI_NUMERICHOST.

 

ai_family

Protocol family, such as PF_INET.

 

ai_socktype

Socket type, such as SOCK_RAW, SOCK_STREAM, or SOCK_DGRAM.

 

ai_protocol

Protocol, such as IPPROTO_TCP or IPPROTO_UDP. For protocols other than IPv4 and IPv6, set ai_protocol to zero.

 

ai_addrlen

Length of the ai_addr member, in bytes.

 

ai_canonname

Canonical name for the host.

 

ai_addr

Pointer to a sockaddr structure.

 

ai_next

Pointer to the next structure in a linked list. This parameter is set to NULL in the last addrinfo structure of a linked list.

Header file

<winsock2.h>, <ws2tcpip.h>.

Remark

Declared in ws2tcpip.h; include wspiapi.h for Windows 95/98/Me, Windows 2000 and Windows NT.

 

Table 1

 

freeaddrinfo()

 

Item

Description

Function

freeaddrinfo().

Use

Frees address information that the getaddrinfo() function dynamically allocates in its addrinfo structures.

Prototype

void freeaddrinfo(struct addrinfo* ai);

Parameters

ai

[in] Pointer to the addrinfo structure or linked list of addrinfo structures to be freed. All dynamic storage pointed to within the addrinfo structure(s) is also freed.

Return value

This function has no return values.

Include file

<winsock2.h>, <ws2tcpip.h>

Library

ws2_32.lib

Remark

Declared in ws2tcpip.h; include wspiapi.h for Windows 95/98/Me, Windows 2000 and Windows NT. The freeaddrinfo() function frees the initial addrinfo structure pointed to in its ai parameter, including any buffers to which its members point, then continues freeing any addrinfo structures linked by its ai_next member. The freeaddrinfo() function continues freeing linked structures until a NULL ai_next member is encountered. Macros in the Winsock header file define the mixed-case function name FreeAddrInfo() to freeaddrinfo(); either spelling is acceptable.

 

Table 2

 

 

 

Program Example

 

For the program example that demonstrates the use of the send() functions on server and client please refer to the previous program examples.

 

Complete client-server program example

 

The following codes are server and client program examples that used the previous discussed Winsock functions and structures. In this case, to make the client-server communication possible you have to make the server settings (through the arguments- protocol, port number etc.) must match with the client settings. For example if you choose to run the UDP server, the client also must be UDP client. Please run the server program first and you can run the client from different computers. In this example the server and client have been run using the default values of arguments on local Windows Xp Pro machine.

 

/* Server program example for IPv4 */

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

 

#define DEFAULT_PORT 2007

// default TCP socket type

#define DEFAULT_PROTO SOCK_STREAM

 

void Usage(char *progname)

{

    fprintf(stderr,"Usage: %s -p [protocol] -e [port_num] -i [ip_address]\n", progname);

    fprintf(stderr,"Where:\n\t- protocol is one of TCP or UDP\n");

    fprintf(stderr,"\t- port_num is the port to listen on\n");

    fprintf(stderr,"\t- ip_address is the ip address (in dotted\n");

    fprintf(stderr,"\t  decimal notation) to bind to. But it is not useful here...\n");

    fprintf(stderr,"\t- Hit Ctrl-C to terminate server program...\n");

    fprintf(stderr,"\t- The defaults are TCP, 2007 and INADDR_ANY.\n");

    WSACleanup();

    exit(1);

}

 

int main(int argc, char **argv)

{

 

    char Buffer[128];

    char *ip_address= NULL;

    unsigned short port=DEFAULT_PORT;

    int retval;

    int fromlen;

    int i;

    int socket_type = DEFAULT_PROTO;

    struct sockaddr_in local, from;

    WSADATA wsaData;

    SOCKET listen_socket, msgsock;

 

    /* Parse arguments, if there are arguments supplied */

    if (argc > 1)

       {

        for(i=1; i<argc; i++)

              {

                     // switches or options...

            if ((argv[i][0] == '-') || (argv[i][0] == '/'))

                     {

                // Change to lower...if any

                           switch(tolower(argv[i][1]))

                           {

                                  // if -p or /p

                    case 'p':

                        if (!stricmp(argv[i+1], "TCP"))

                            socket_type = SOCK_STREAM;

                        else if (!stricmp(argv[i+1], "UDP"))

                            socket_type = SOCK_DGRAM;

                        else

                            Usage(argv[0]);

                        i++;

                        break;

                                  // if -i or /i, for server it is not so useful...

                    case 'i':

                        ip_address = argv[++i];

                        break;

                                  // if -e or /e

                    case 'e':

                        port = atoi(argv[++i]);

                        break;

                                  // No match...

                    default:

                        Usage(argv[0]);

                        break;

                }

            }

            else

                Usage(argv[0]);

        }

    }

   

       // Request Winsock version 2.2

    if ((retval = WSAStartup(0x202, &wsaData)) != 0)

       {

        fprintf(stderr,"Server: WSAStartup() failed with error %d\n", retval);

        WSACleanup();

        return -1;

    }

    else

       printf("Server: WSAStartup() is OK.\n");

   

    if (port == 0)

       {

        Usage(argv[0]);

    }

 

    local.sin_family = AF_INET;

    local.sin_addr.s_addr = (!ip_address) ? INADDR_ANY:inet_addr(ip_address);

 

    /* Port MUST be in Network Byte Order */

    local.sin_port = htons(port);

    // TCP socket

    listen_socket = socket(AF_INET, socket_type,0);

   

    if (listen_socket == INVALID_SOCKET){

        fprintf(stderr,"Server: socket() failed with error %d\n", WSAGetLastError());

        WSACleanup();

        return -1;

    }

    else

       printf("Server: socket() is OK.\n");

 

       // bind() associates a local address and port combination with the

    // socket just created. This is most useful when the application is a

    // server that has a well-known port that clients know about in advance.

    if (bind(listen_socket, (struct sockaddr*)&local, sizeof(local)) == SOCKET_ERROR)

       {

        fprintf(stderr,"Server: bind() failed with error %d\n", WSAGetLastError());

        WSACleanup();

        return -1;

    }

    else

              printf("Server: bind() is OK.\n");

 

       // So far, everything we did was applicable to TCP as well as UDP.

    // However, there are certain steps that do not work when the server is

    // using UDP. We cannot listen() on a UDP socket.

    if (socket_type != SOCK_DGRAM)

       {

        if (listen(listen_socket,5) == SOCKET_ERROR)

              {

            fprintf(stderr,"Server: listen() failed with error %d\n", WSAGetLastError());

            WSACleanup();

            return -1;

        }

       else

              printf("Server: listen() is OK.\n");

    }

    printf("Server: %s: I'm listening and waiting connection\non port %d, protocol %s\n", argv[0], port, (socket_type == SOCK_STREAM)?"TCP":"UDP");

   

       while(1)

       {

        fromlen =sizeof(from);

 

        // accept() doesn't make sense on UDP, since we do not listen()

        if (socket_type != SOCK_DGRAM)

              {

            msgsock = accept(listen_socket, (struct sockaddr*)&from, &fromlen);

            if (msgsock == INVALID_SOCKET)

           {

                fprintf(stderr,"Server: accept() error %d\n", WSAGetLastError());

                WSACleanup();

                return -1;

            }

           else

              printf("Server: accept() is OK.\n");

              printf("Server: accepted connection from %s, port %d\n", inet_ntoa(from.sin_addr), htons(from.sin_port)) ;

           

        }

        else

            msgsock = listen_socket;

 

        // In the case of SOCK_STREAM, the server can do recv() and

        // send() on the accepted socket and then close it.

        // However, for SOCK_DGRAM (UDP), the server will do

        // recvfrom() and sendto()  in a loop.

        if (socket_type != SOCK_DGRAM)

            retval = recv(msgsock, Buffer, sizeof(Buffer), 0);

       

       else

       {

            retval = recvfrom(msgsock,Buffer, sizeof(Buffer), 0, (struct sockaddr *)&from, &fromlen);

            printf("Server: Received datagram from %s\n", inet_ntoa(from.sin_addr));

        }

           

        if (retval == SOCKET_ERROR)

              {

            fprintf(stderr,"Server: recv() failed: error %d\n", WSAGetLastError());

            closesocket(msgsock);

            continue;

        }

       else

            printf("Server: recv() is OK.\n");

 

        if (retval == 0)

              {

            printf("Server: Client closed connection.\n");

            closesocket(msgsock);

            continue;

        }

        printf("Server: Received %d bytes, data \"%s\" from client\n", retval, Buffer);

 

        printf("Server: Echoing the same data back to client...\n");

        if (socket_type != SOCK_DGRAM)

            retval = send(msgsock, Buffer, sizeof(Buffer), 0);

        else

            retval = sendto(msgsock, Buffer, sizeof(Buffer), 0, (struct sockaddr *)&from, fromlen);

       

              if (retval == SOCKET_ERROR)

              {

                     fprintf(stderr,"Server: send() failed: error %d\n", WSAGetLastError());

               }

              else

                     printf("Server: send() is OK.\n");

 

        if (socket_type != SOCK_DGRAM)

       {

            printf("Server: I'm waiting more connection, try running the client\n");

            printf("Server: program from the same computer or other computer...\n");

            closesocket(msgsock);

        }

        else

            printf("Server: UDP server looping back for more requests\n");

        continue;

    }

       return 0;

}

 

 

Figure 1

 

The following is the client program.

 

// Client program example

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

 

#define DEFAULT_PORT 2007

// TCP socket type

#define DEFAULT_PROTO SOCK_STREAM

 

void Usage(char *progname)

{

    fprintf(stderr,"Usage: %s -p [protocol] -n [server name/IP] -e [port_num] -l [iterations]\n", progname);

    fprintf(stderr,"Where:\n\tprotocol is one of TCP or UDP\n");

    fprintf(stderr,"\t- server is the IP address or name of server\n");

    fprintf(stderr,"\t- port_num is the port to listen on\n");

    fprintf(stderr,"\t- iterations is the number of loops to execute.\n");

    fprintf(stderr,"\t- (-l by itself makes client run in an infinite loop,\n");

    fprintf(stderr,"\t- Hit Ctrl-C to terminate it)\n");

    fprintf(stderr,"\t- The defaults are TCP , localhost and 2007\n");

    WSACleanup();

    exit(1);

}

 

int main(int argc, char **argv)

{

    char Buffer[128];

       // default to localhost

    char *server_name= "localhost";

    unsigned short port = DEFAULT_PORT;

    int retval, loopflag = 0;

    int i, loopcount, maxloop=-1;

    unsigned int addr;

    int socket_type = DEFAULT_PROTO;

    struct sockaddr_in server;

    struct hostent *hp;

    WSADATA wsaData;

    SOCKET  conn_socket;

 

    if (argc >1)

       {

        for(i=1; i<argc; i++)

        {

            if ((argv[i][0] == '-') || (argv[i][0] == '/'))

           {

                switch(tolower(argv[i][1]))

                 {

                    case 'p':

                        if (!stricmp(argv[i+1], "TCP"))

                            socket_type = SOCK_STREAM;

                        else if (!stricmp(argv[i+1], "UDP"))

                            socket_type = SOCK_DGRAM;

                        else

                            Usage(argv[0]);

                        i++;

                        break;

                    case 'n':

                        server_name = argv[++i];

                        break;

                    case 'e':

                        port = atoi(argv[++i]);

                        break;

                    case 'l':

                        loopflag =1;

                        if (argv[i+1]) {

                            if (argv[i+1][0] != '-')

                                maxloop = atoi(argv[i+1]);

                        }

                        else

                            maxloop = -1;

                        i++;

                        break;