Socket Programming

Document Sample
Socket Programming Powered By Docstoc
					Socket Programming
 What is a socket?
 Using sockets
   Types (Protocols)
   Associated functions
   Styles


     We will look at using sockets in C




                                           1
What is a socket?
 An interface between application and
  network
    The application creates a socket
    The socket type dictates the style of
     communication
       • reliable vs. best effort
       • connection-oriented vs. connectionless
 Once configured the application can
   pass data to the socket for network
    transmission
   receive data from the socket (transmitted
    through the network by some other host)
                                                  2
  Two essential types of sockets
 SOCK_STREAM                          SOCK_DGRAM
       a.k.a. TCP                         a.k.a. UDP
       reliable delivery                  unreliable delivery
       in-order guaranteed                no order guarantees
       connection-oriented                no notion of “connection” –
       bidirectional                       app indicates dest. for each
                                            packet
                                           can send or receive
  App

3 2                                          App                      D1
    1
         socket               Dest.
                                         3 2
                                             1
                                                   socket              D2

                                                                 D3
           Q: why have type SOCK_DGRAM?
                                                                       3
Socket Creation in C: socket
 int s = socket(domain, type, protocol);
    s: socket descriptor, an integer (like a file-handle)
    domain: integer, communication domain
        • e.g., PF_INET (IPv4 protocol) – typically used
      type: communication type
        • SOCK_STREAM: reliable, 2-way, connection-based
          service
        • SOCK_DGRAM: unreliable, connectionless,
        • other values: need root permission, rarely used, or
          obsolete
    protocol: specifies protocol (see file /etc/protocols
     for a list of options) - usually set to 0
 NOTE: socket call does not specify where data will be
  coming from, nor where it will be going to – it just
  creates the interface!                                   4
A Socket-eye view of the
Internet
      medellin.cs.columbia.edu
      (128.59.21.14)

                                                newworld.cs.umass.edu
                                                (128.119.245.93)

                  cluster.cs.columbia.edu
                  (128.59.21.14, 128.59.16.7,
                  128.59.16.5, 128.59.16.4)




 Each host machine has an IP address
 When a packet arrives at a host

                                                                        5
  Ports
 Each host has 65,536
                            Port 0
  ports
                            Port 1
 Some ports are
 reserved for specific
 apps                       Port 65535

   20,21: FTP
                      A socket provides an interface
   23: Telnet          to send data to/from the
   80: HTTP            network through a port
   see RFC 1700 (about
    2000 ports are
    reserved)
                                                        6
Addresses, Ports and Sockets
 Like apartments and mailboxes
    You are the application
    Your apartment building address is the address
    Your mailbox is the port
    The post-office is the network
    The socket is the key that gives you access to the right
     mailbox (one difference: assume outgoing mail is placed
     by you in your mailbox)


 Q: How do you choose which port a socket
  connects to?


                                                                7
The bind function
 associates and (can exclusively) reserves a port
  for use by the socket
 int status = bind(sockid, &addrport, size);
      status: error status, = -1 if bind failed
      sockid: integer, socket descriptor
      addrport: struct sockaddr, the (IP) address and port of the
       machine (address usually set to INADDR_ANY – chooses a
       local address)
      size: the size (in bytes) of the addrport structure
 bind can be skipped for both types of sockets.
  When and why?


                                                                     8
Skipping the bind
 SOCK_DGRAM:
   if only sending, no need to bind. The OS finds a
    port each time the socket sends a pkt
   if receiving, need to bind

 SOCK_STREAM:
   destination determined during conn. setup
   don’t need to know port sending from (during
    connection setup, receiving end is informed of
    port)



                                                       9
Connection Setup                     (SOCK_STREAM)

 Recall: no connection setup for SOCK_DGRAM
 A connection occurs between two kinds of
  participants
      passive: waits for an active participant to request
       connection
      active: initiates connection request to passive side
 Once connection is established, passive and active
  participants are “similar”
      both can send & receive data
      either can terminate the connection




                                                              10
Connection setup cont’d
 Passive participant         Active participant
    step 1: listen (for
     incoming requests)
                                   step 2: request &
    step 3: accept (a
                                    establish connection
     request)
    step 4: data transfer
                                   step 4: data transfer
 The accepted
  connection is on a new         Passive Participant
  socket                       a-sock-1    l-sock   a-sock-2
 The old socket
  continues to listen for
  other active
  participants                  socket               socket
 Why?
                              Active 1              Active 2
                                                               11
Connection setup: listen & accept
 Called by passive participant
 int status = listen(sock, queuelen);
    status: 0 if listening, -1 if error
    sock: integer, socket descriptor
    queuelen: integer, # of active participants that can
      “wait” for a connection
    listen is non-blocking: returns immediately

 int s = accept(sock, &name, &namelen);
    s: integer, the new socket (used for data-transfer)
    sock: integer, the orig. socket (being listened on)
    name: struct sockaddr, address of the active participant
    namelen: sizeof(name): value/result parameter
        • must be set appropriately before call
        • adjusted by OS upon return
      accept is blocking: waits for connection before returning
                                                                   12
connect call
 int status = connect(sock, &name, namelen);
    status: 0 if successful connect, -1 otherwise
    sock: integer, socket to be used in connection
    name: struct sockaddr: address of passive
     participant
    namelen: integer, sizeof(name)

 connect is blocking




                                                      13
Sending / Receiving Data
 With a connection (SOCK_STREAM):
   int count = send(sock, &buf, len, flags);
        •   count: # bytes transmitted (-1 if error)
        •   buf: char[], buffer to be transmitted
        •   len: integer, length of buffer (in bytes) to transmit
        •   flags: integer, special options, usually just 0
    int    count = recv(sock, &buf, len, flags);
        •   count: # bytes received (-1 if error)
        •   buf: void[], stores received bytes
        •   len: # bytes received
        •   flags: integer, special options, usually just 0
      Calls are blocking [returns only after data is sent
       (to socket buf) / received]
                                                                    14
  Sending / Receiving Data                             (cont’d)
 Without a connection (SOCK_DGRAM):
      int count = sendto(sock, &buf, len, flags, &addr, addrlen);
        • count, sock, buf, len, flags: same as send
        • addr: struct sockaddr, address of the destination
        • addrlen: sizeof(addr)
      int count = recvfrom(sock, &buf, len, flags, &addr,
                            &addrlen);
        • count, sock, buf, len, flags: same as recv
        • name: struct sockaddr, address of the source
        • namelen: sizeof(name): value/result parameter
 Calls are blocking [returns only after data is sent (to
  socket buf) / received]

                                                                  15
close
 When finished using a socket, the socket
  should be closed:
 status = close(s);
   status: 0 if successful, -1 if error
   s: the file descriptor (socket being closed)

 Closing a socket
   closes a connection (for SOCK_STREAM)
   frees up the port used by the socket




                                                   16
The struct sockaddr
 The generic:                  The Internet-specific:
   struct sockaddr {              struct sockaddr_in {
       u_short sa_family;             short sin_family;
       char sa_data[14];              u_short sin_port;
   };                                 struct in_addr sin_addr;
                                      char sin_zero[8];
                                  };
      sa_family
                                   sin_family = AF_INET
        • specifies which
                                   sin_port: port # (0-65535)
          address family is
          being used               sin_addr: IP-address

        • determines how the       sin_zero: unused
          remaining 14 bytes
          are used

                                                                 17
 Address and port byte-ordering
  Address and port are stored as
    integers                                        struct in_addr {
        u_short sin_port; (16 bit)                   u_long s_addr;
        in_addr sin_addr; (32 bit)                 };
 Problem:
    different machines / OS’s use different word orderings
         • little-endian: lower bytes first
         • big-endian: higher bytes first
      these machines may communicate with one another over the
       network
                   Big-Endian
                   machine                    Little-Endian
                                                                    12.40.119.128
 128.119.40.12                                machine

          128    119   40    12                    128   119   40     12
                                                                               18
Solution: Network Byte-Ordering
 Defs:
    Host Byte-Ordering: the byte ordering used by
     a host (big or little)
    Network Byte-Ordering: the byte ordering used
     by the network – always big-endian
 Any words sent through the network should be
  converted to Network Byte-Order prior to
  transmission (and back to Host Byte-Order once
  received)
 Q: should the socket perform the conversion
  automatically?
 Q: Given big-endian machines don’t need
  conversion routines and little-endian machines do,
  how do we avoid writing two versions of code?
                                                       19
 UNIX’s byte-ordering funcs
 u_long htonl(u_long x);         u_long ntohl(u_long x);
 u_short htons(u_short x);       u_short ntohs(u_short x);


  On big-endian machines, these routines do nothing
  On little-endian machines, they reverse the byte
    order
                   Big-Endian
                   machine         Little-Endian12       40 119 128
                                                         128.119.40.12
128 119 40
 128.119.40.12    12
                                   machine




                                                                   ntohl
          128    119   40   12          128   119   40     12


  Same code would have worked regardless of endian-
    ness of the two machines                                       20
Dealing with blocking calls
 Many of the functions we saw block until a certain
  event
      accept: until a connection comes in
      connect: until the connection is established
      recv, recvfrom: until a packet (of data) is received
      send, sendto: until data is pushed into socket’s buffer
        • Q: why not until received?
 For simple programs, blocking is convenient
 What about more complex programs?
   multiple connections
   simultaneous sends and receives
   simultaneously doing non-networking processing

                                                                 21
Dealing w/ blocking (cont’d)
 Options:
   create multi-process or multi-threaded code
   turn off the blocking feature (e.g., using the fcntl file-
    descriptor control function)
   use the select function call.

 What does select do?
   can be permanent blocking, time-limited blocking or non-
    blocking
   input: a set of file-descriptors
   output: info on the file-descriptors’ status
   i.e., can identify sockets that are “ready for use”: calls
    involving that socket will return immediately

                                                                 22
Other useful functions
 bzero(char* c, int n): 0’s n bytes starting at c
 gethostname(char *name, int len): gets the name of
  the current host
 gethostbyaddr(char *addr, int len, int type): converts
  IP hostname to structure containing long integer
 inet_addr(const char *cp): converts dotted-decimal
  char-string to long integer
 inet_ntoa(const struct in_addr in): converts long to
  dotted-decimal notation

 Warning: check function assumptions about byte-
  ordering (host or network). Often, they assume
  parameters / return solutions in network byte-
  order                                                    23
Release of ports
 Sometimes, a “rough” exit from a program (e.g.,
  ctrl-c) does not properly free up a port
 Eventually (after a few minutes), the port will be
  freed
 To reduce the likelihood of this problem, include
  the following code:
       #include <signal.h>
       void cleanExit(){exit(0);}
      in socket code:
       signal(SIGTERM, cleanExit);
       signal(SIGINT, cleanExit);

                                                       24
Example – Daytime
Server/Client
                 Application protocol
Daytime client                          Daytime server


 Socket API                              Socket API

                   TCP protocol
    TCP                                     TCP

                   IP protocol
      IP                                     IP

                   MAC-level protocol
  MAC driver                             MAC driver
                   Actual data flow
                                                  MAC = media
                      Network                     access control
                                                             25
TCP Daytime client

 Connects to a daytime server
 Retrieves the current date and time


% gettime  130.245.1.44
Thu Sept 05 15:50:00 2002




                                        26
#include          "unp.h"

int main(int argc, char **argv)
{
        int sockfd, n;
        char recvline[MAXLINE + 1];
        struct sockaddr_in servaddr;

           if( argc != 2 )err_quit(“usage : gettime <IP address>”);

        /* Create a TCP socket */
        if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
                err_sys("socket error");


        /* Specify server’s IP address and port */
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(13); /* daytime server port */
        if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
                err_quit("inet_pton error for %s", argv[1]);




                                                                      27
    /* Connect to the server */
    if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0)
             err_sys("connect error");

     /* Read the date/time from socket */
     while ( (n = read(sockfd, recvline, MAXLINE)) > 0) {
             recvline[n] = 0;        /* null terminate */
             printf(“%s”, recvline);
     }

     if (n < 0) err_sys("read error");

     close(sockfd);
}




                                                                   28
Simplifying error-handling

int Socket(int family, int type, int protocol)
{
        int n;

        if ( (n = socket(family, type, protocol)) < 0)
                err_sys("socket error");

        return n;
}




                                                         29
TCP Daytime Server

 Waits for requests from Client
 Accepts client connections
 Send the current time
 Terminates connection and goes back waiting for more
  connections.




                                                         30
#include        "unp.h"
#include        <time.h>

int main(int argc, char **argv)
{
        int   listenfd, connfd;
        struct sockaddr_in servaddr;
        char buff[MAXLINE];
        time_t ticks;

        /* Create a TCP socket */
        listenfd = Socket(AF_INET, SOCK_STREAM, 0);

        /* Initialize server’s address and well-known port */
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family      = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port        = htons(13);   /* daytime server */

        /* Bind server’s address and port to the socket */
        Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));




                                                                       31
    /* Convert socket to a listening socket */
     Listen(listenfd, LISTENQ);

     for ( ; ; ) {
             /* Wait for client connections and accept them */
             connfd = Accept(listenfd, (SA *) NULL, NULL);

             /* Retrieve system time */
             ticks = time(NULL);
             snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));

             /* Write to socket */
             Write(connfd, buff, strlen(buff));

             /* Close the connection */
             Close(connfd);
     }
}




                                                                         32
The Socket Structure
                          INET Address

struct in_addr {
   in_addr_t s_addr;    /* 32-bit IPv4 address */
}

                          INET Socket

Struct sockaddr_in {
   uint8_t sin_len; /* length of structure (16) */
   sa_family_t sin_family; /* AF_INET */
   in_port_t sin_port; /* 16-bit TCP/UDP port number */
   struct in_addr sin_addr; /* 32-bit IPv4 address */
   char sin_zero[8]; /* unused */
}



                                                          33
UDP Client Code
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <errno.h>
 #define MY_PORT_ID          6089
    #define SERVER_PORT_ID 6090
    #define SERV_HOST_ADDR "128.119.40.186"
   main(){ int sockid, retcode;
    struct sockaddr_in my_addr, server_addr;
   char msg[12];



                                                34
UDP Client (cont.)
 printf("Client: creating socket\n");
     if ( (sockid = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    { printf("Client: socket failed: %d\n",errno); exit(0); }
    printf("Client: binding my local socket\n"); bzero((char *)
    &my_addr, sizeof(my_addr));
     my_addr.sin_family = AF_INET;
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
     my_addr.sin_port = htons(MY_PORT_ID);
   if ( (bind(sockid, (struct sockaddr *) &my_addr,
    sizeof(my_addr)) < 0) )      { printf("Client: bind fail:
    %d\n",errno); exit(0); }



                                                                   35
UDP Client (fin)
    printf("Client: creating addr structure for server\n");
   bzero((char *) &server_addr, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
   server_addr.sin_addr.s_addr =
    inet_addr(SERV_HOST_ADDR);
    server_addr.sin_port = htons(SERVER_PORT_ID);
    printf("Client: initializing message and sending\n");
    sprintf(msg, "Hello world"); retcode =
    sendto(sockid,msg,12,0,(struct sockaddr *) &server_addr,
                     sizeof(server_addr));
      if (retcode <= -1) {printf("client: sendto failed:
    %d\n",errno); exit(0); }
   /* close socket */
     close(sockid); }

                                                                36
UDP Server
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <errno.h>
 #define MY_PORT_ID        6090   /* a number > 5000 */
 main(){
 int sockid, nread, addrlen;
  struct sockaddr_in my_addr, client_addr;
 char msg[50];



                                                           37
UDP Server (cont)
 printf("Server: creating socket\n");
      if ( (sockid = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    { printf("Server: socket error: %d\n",errno); exit(0); }
      printf("Server: binding my local socket\n");
      bzero((char *) &my_addr, sizeof(my_addr));
    my_addr.sin_family = AF_INET;
    my_addr.sin_addr.s_addr = htons(INADDR_ANY);
    my_addr.sin_port = htons(MY_PORT_ID);
     if ( (bind(sockid, (struct sockaddr *) &my_addr,
    sizeof(my_addr)) < 0) )       { printf("Server: bind fail:
    %d\n",errno); exit(0); }



                                                                 38
UDP Server (end)
 printf("Server: starting blocking message
  read\n");
 nread = recvfrom(sockid,msg,11,0, (struct
  sockaddr *) &client_addr, &addrlen);
 printf("Server: return code from read is
  %d\n",nread);
 if (nread >0) printf("Server: message is:
  %s\n",msg);
 close(sockid);
 }


                                              39
Ports
 Port - A 16-bit number that identifies the
  application process that receives an incoming
  message.

 Reserved ports or well-known ports (0 to 1023)
   Standard ports for well-known applications.
     Telnet (23), ftp(21), http (80).
     See /etc/services file on any UNIX machine for listing of services on
     reserved ports.


 Ephemeral ports (1024-65535)
   For ordinary user-developed programs.



                                                                             40
 Associations

 A   socket address is the triple:
               {protocol, local-IP, local-port}
   For example,
                     {tcp, 130.245.1.44, 23}

 An   association is the 5-tuple that completely specifies
  the two end-points that comprise a connection:
      {protocol, local-IP, local-port, remote-IP, remote-port}
For example:
       {tcp, 130.245.1.44, 23, 130.245.1.45, 1024}


                                                                 41
Associations….
 A   half-association is
             {protocol, local-IP, local-port}
                            or
         {protocol, remote-IP, remote-port}
which specify each half of the connection.

 The half-association is also called a   socket or a
  transport address.




                                                        42
UDP Daytime Client and Server
 Server waits for requests on a known port.


 Client sends a UDP request to server.


 Server responds with daytime info.


 No connection establishment!


 No reliability!




                                               43
UDP Client




             44
#include          "unp.h"

int main(int argc, char **argv)
{
        int sockfd, n, servlen;
        char req[10], recvline[MAXLINE + 1];
        struct sockaddr_in servaddr;

           if( argc != 2 )err_quit(“usage : gettime <IP address>”);

        /* Create a UDP socket */
        sockfd = Socket(AF_INET, SOCK_DGRAM, 0);



        /* Specify server’s IP address and port */
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(13); /* daytime server port */
        Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);




                                                                      45
         /* Send message to server requesting date/time */
       strcpy(req, “GET_TIME”);
       Sendto(sockfd, req, strlen(req), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));


          /* Read date/time from the socket */
          servlen = sizeof(servaddr);
         n= Recvfrom(sockfd, recvline, MAXLINE, 0, (struct sockaddr *)&servaddr,
    &servlen);
          recvlen[n] = 0;
          printf(“%s”, recvlen);

        close(sockfd);
}




                                                                                          46
UDP Server




             47
#include        "unp.h"
#include        <time.h>

int main(int argc, char **argv)
{
        int   sockfd, clilen;
         struct sockaddr_in servaddr, cliaddr;
        char buff[MAXLINE], req[REQ_LEN];
        time_t ticks;

        /* Create a socket */
        sockfd = Socket(AF_INET, SOCK_DGRAM, 0);

        /* Initialize server’s address and well-known port */
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family      = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port        = htons(13);   /* daytime server */

        /* Bind server’s address and port to the socket */
        Bind(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr));




                                                                         48
    for ( ; ; ) {
             /* Wait for client request */
             len = sizeof(cliaddr);
             n = Recvfrom( sockfd, req, REQ_LEN, 0, &cliaddr, &clilen);

            /* Retrieve the system time */
          ticks = time(NULL);
          snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));

           /* Send to client*/
           Sendto(sockfd, buff, strlen(buff), 0, &cliaddr, clilen);
    }
}




                                                                          49
TCP Connection Sequence
                              Server   socket()
 Client
                                        bind()
socket()
                                        listen()
connect()   3-way handshake
                                        accept()
write()     data

                                        read()




             data
                                       write()
read()

            EOF
close()                                read()      close()
                                                        50
UDP Connection Sequence
                      Server

Client

                      socket()
 socket()

                       bind()
 sendto()     data

                       recvfrom()




              data
                       sendto()
 recvfrom()


 close()
                                    51
    Socket API summary
   int socket( int family, int type, int protocol)

      Creates a network plug point that enables the client/server to communicate

   int connect( int sockfd, const struct sockaddr *servaddr,
    socklen_t addrlen)

      Enables a client to connect to a server.

   int bind( int sockfd, const struct sockaddr *myaddr,
    socklen_t addrlen)

      Allows a server to specify the IP address/port_number associated with a socket




                                                                               52
Socket API summary…
 int listen(int sockfd, int backlog)
      Allows the server to specify that a socket can be used to accept
        connections.


 int accept(int sockfd, struct sockaddr *client_addr,
  socklen_t *addrlen)

      Allows a server to wait till a new connection request arrives.


 int close(int sockfd)
      Terminates any connection associated with a socket and releases
        the socket descriptor.




                                                                         53
Socket API summary…
 int read(int sockfd, void *buf, int count);
        Read data from a TCP connection.


 int write(int sockfd, void *buf, int count)
    Write data to a TCP connection.

 int sendto(int sockfd, void *msg, … )
        Send a UDP message on a socket to specified destination

 int recvfrom(int sockfd, void *buf, … )
   Recv a UDP message on a socket along with address of sending source.

 Similarly check man pages for sendmsg(), recvmsg().




                                                                          54
Converting Between Address formats


 From ASCII to numeric
    “130.245.1.44”  32-bit network byte ordered value
    inet_aton(…) with IPv4
    inet_pton(…) with IPv4 and IPv6


 From numeric to ASCII
    32-bit value  “130.245.1.44”
    inet_ntoa(…) with IPv4
    inet_ntop(…) with IPv4 and IPv6
    Note – inet_addr(…) obsolete
       • cannot handle broadcast address “255.255.255.255”
         (0xFFFFFFFF)


                                                             55

				
DOCUMENT INFO
Shared By:
Categories:
Tags:
Stats:
views:0
posted:2/12/2013
language:English
pages:55