Unix, C, and C++
Function Reference
Internet

See notes on: General Scheme of Internet Communications
              Port Numbers
              IP Numbers
              Byte Order
              Finding IP addresses
and samples: Sample Internet (IP+TCP) Server Program
             Sample Internet (IP+TCP) Client Program
             Sample IP+UDP Communication Program


Warning: When a function's description says include <sys/types.h>
then <sys/socket.h> it is important that the #includes appear in
that order in your program. The file sys/socket.h makes use of definitions 
that appear in sys/types.h but is too stupid to include it for itself.
Putting those two includes in the wrong order will cause a large number of 
meaningless error messages from the compiler.



  int gethostname(char * name, int maxlen)
      Purpose: Find the computer's name.
      include: <unistd.h>
      The name of the computer (e.g. rabbit.eng.miami.edu) is stored in
      the string name, up to a maximum of maxlen characters.
      returns <0 for error, 0 for success.



  int gethostid(void)
      include: <unistd.h>
      returns An integer that is supposed to uniquely identify the
              computer, usually its IP number
              note: valid results can be negative.
      WARNING: This function can not be relied upon; it relies on optional system set-up
      procedures that are often not performed. On many systems it will return zero.
      For reliable results, use gethostname then gethostbyname instead



  hostent * gethostbyname(char * name)
      Purpose: Find any computer's IP address
      include: <netdb.h>
      name = computer name, such as "rabbit", "rabbit.eng.miami.edu", or "129.171.33.6"
      returns NULL in case of error (use herror, not perror, etc to display), or
                     a pointer to a hostent struct. The fields of a hostent are:
             char * h_name          the official name
             char * * h_aliases     list of alternate names, NULL at end
             int h_addr_type        what kind of address: expect AF_INET
             int h_length           bytes in each address: expect 4
             char * h_addr          primary address - not a string
             char * * h_addr_list   all addresses, not strings, NULL at end
      usually h_addr is the only interesting field. It is not a string, but a list
          of bytes giving the address, e.g. { 129, 171, 33, 6 }
      h_addr, and all h_addr_list[i], are usually type-cast to (in_addr *) before use.
      If the input string, name, is in numeric form, that numeric form is returned as 
          h_name, h_addr, and h_addr_list[0]; no aliases are provided, no 'reverse
          translation' is performed.
      IP addresses are provided in Network Byte Order, so ntohl may be required.
      See Simple Sample Program, Full Sample Program



  int socket(int domain, int type, int protocol)
      Purpose: Create a file-like object capable of internet communications
      include: <sys/types.h> then <sys/socket.h>
      domain = AF_INET if you want to use IP, there are many others.
      type = SOCK_STREAM if you want TCP, or SOCK_DGRAM if you want UDP, there are a few others
      protocol = 0, except in almost unheard-of circumstances
      returns <0 for error, or an integer file decriptor exactly as returned by open.
      Note using UDP the socket is now ready for use with send and recvfrom;
           using TCP a connection to another computer must first be made with connect or accept
      See Sample Server Program or Sample Client Program



  int bind(int socket, sockaddr * description, int size)
      include: <sys/types.h> then <sys/socket.h>
      socket = a socket as created by socket
      description = a pointer to a sockaddr_in, but typecast as a pointer to a sockaddr.
      size = the size in bytes of a sockaddr_in
      returns <0 for error, positive otherwise
      Purpose: (for servers only) After a socket has been created, and a sockaddr_in has 
           been set up to describe the service to be establised, this sets up the socket to be a 
           server socket on the appropriate port.
      See Sample Server Program



  int listen(int socket, int length)
      include: <sys/types.h> then <sys/socket.h>
      socket = a socket as created by socket and set up with bind as a server port
      length = queue length for pending connections, typically 3
      returns <0 for error, positive otherwise
      Purpose: (for servers only) After a socket has been created and bound to a port, this 
           sets up a queue of pending client connections so that it is ready to listen for them.
      See Sample Server Program



  int accept(int socket, sockaddr * description, unsinged int * size)
      include: <sys/types.h> then <sys/socket.h>
      socket = a socket as created by socket and set up with bind and listen
      description = a pointer to an uninitialised sockaddr_in, typecast as a pointer to a sockaddr.
      length = the address of an unsigned int variable
      returns <0 for error, otherwise an int describing a file exactly as returned by open
           on which read and write operations directly to the client may be performed.
      Purpose: (for servers only) After a socket has been created, bound to a port, and 
           listened on, this waits for a client to request a connection.
      See Sample Server Program



  int connect(int socket, sockaddr * description, int size)
      include: <sys/types.h> then <sys/socket.h>
      socket = a socket as created by socket
      description = a pointer to a sockaddr_in, but typecast as a pointer to a sockaddr.
      size = the size in bytes of a sockaddr_in
      returns <0 for error, otherwise an int describing a file exactly as returned by open
           on which read and write operations directly to the server may be performed.
      Purpose: (for clients only) After a socket has been created, and a sockaddr_in has 
           been set up to describe the server to be connected to, this attempts to make 
           the connection
      See Sample Client Program



  struct sockaddr
  { char sa_len;              // total size of the struct in bytes
    char sa_family;           // usually AF_INET
    char sa_data[LENGTH]; };  // just a place-holder
      include: <sys/socket.h>
      Purpose: the functions bind and connect use a sockaddr to specify the kind of connection wanted.
            Actually, programs never create a sockaddr, but instead make a sockaddr_in which contains
            all the information that is needed, and typecast as a sockaddr before passing to the function.
      See Sample Server Program or Sample Client Program



  struct sockaddr_in
  { char sin_len;            // total size of the struct in bytes
    char sin_family;         // usually AF_INET
    short int sin_port;      // port number, in network format, use htons
    in_addr sin_addr;        // for clients: IP address of server in network format, use htonl
                             // for servers: usually htonl(INADDR_ANY) to accept connections from anywhere.
    char sin_zero[8]; };     // unused.
      include: <netinet/in.h>
      See Sample Server Program or Sample Client Program



  struct in_addr
  { int s_addr; };           // the IP address, network format, use htonl
      include: <netinet/in.h>
      Purpose: Used to represent an IP address in a sockaddr_in. An absolute folly, as it is exactly
           equivalent to an int.



  int sendto(int socket, char *data, int numbytes, int flags, sockaddr *destination, int dstsize)
      include: <sys/types.h> then <sys/socket.h>
      Purpose: Send data. This function is for UDP sockets, not TCP ones.
      socket = a socket as created by socket
      data = pointer to data to be transmitted (can be any type)
      numbytes = number of bytes to be transmitted
      flags = normally 0, but can be MSG_EOR to indicate that this is a complete transmission
              (like "over" on a walkie-talkie), or MSG_EOF (like "out").
      destination = a pointer to a sockaddr_in, but typecast as a pointer to a sockaddr.
      dstsize = the size in bytes of a sockaddr_in
      returns <0 for error, otherwise the number of bytes successfully sent.
      See Sample UDP Program



  int recvfrom(int socket, char *data, int maxnumbytes, int flags, sockaddr *source, int srcsize)
      include: <sys/types.h> then <sys/socket.h>
      Purpose: wait for and receive data. This function is for UDP sockets, not TCP ones.
      socket = a socket as created by socket
      data = pointer to memory to receive data (can be any type)
      max numbytes = maximum number of bytes to be accepted in a single read
      flags = normally 0, but can be MSG_PEEK to look at a message while still leaving it
              in the buffer so that it can be read again later.
      source = a pointer to a sockaddr_in, but typecast as a pointer to a sockaddr.
               The IP address and port number of the sender will be put in here.
               May be NULL if you don't care who the sender is.
      srcsize = the size in bytes of a sockaddr_in
      returns <0 for error, otherwise the number of bytes actually received.
      See Sample UDP Program



  char * inet_ntoa(in_addr a)
      include: <netinet/in.h> and <arpa/inet.h>
      Purpose: Convert an IP address in the internal format as retrieved by gethostbyname
              (i.e. a big-endian byte list) into a string suitable for printing.
              Result format example: "129.171.33.6"
      See Sample Program for use



  int htonl(int ip)
      include: <sys/param.h>
      Purpose: converts an IP address in the computers integer format to the standard network format
              note: valid results can be negative.
      See Sample Program for use



  int ntohl(int ip)
      include: <sys/param.h>
      Purpose: converts an IP address in the standard network format to the computers integer format 
              note: valid results can be negative.
      See Sample Program for use



  int htons(int pn)
      include: <sys/param.h>
      Purpose: converts a port number in the computers integer format to the standard network format



  int ntohs(int pn)
      include: <sys/param.h>
      Purpose: converts a port number in the standard network format to the computers integer format 







General Scheme of Internet Communications

First make the choice of protocol: TCP or UDP: If TCP is chosen, of the communicating applications one must act as a server and the other as a client. The server sets up a port and listens to it for incoming connections. The client must know the server's port number; once the server is running, the client makes a connection to it, then two-way communications can begin.

Stages for a TCP server (see
Server Sample Program):
  1. Create an Internet Stream socket
  2. Create a sockaddr_in object stating the port number and the kind of connections to be accepted
  3. Bind the socket to its port
  4. Tell the socket to listen for incoming connections
  5. Wait for and accept an incoming connection request. The result of accept is a unix-level file descriptor; reads and writes on it are direct communications with the client
  6. Optionally fork a new subprocess to deal with this client. This leaves the original process free to immediately accept another client connection by looping back to the accept step
  7. Optionally create a C FILE* to allow higher-level i/o functions to be used
  8. Communicate with the client
  9. Close the connection to the client
  10. If communications are being carried out by a subprocess, then exit to terminate it
  11. If further connections are to be accepted, loop back to the accept step
  12. To terminate the server, close the original socket
Stages for a TCP client (see Client Sample Program):
  1. Look up the server's IP address
  2. Create an Internet Stream socket
  3. Create a sockaddr_in object stating the server's IP address and port number
  4. Connect the socket to the server
  5. The socket behaves as a unix-level file descriptor; reads and writes on it are direct communications with the server
  6. Optionally create a C FILE* to allow higher-level i/o functions to be used
  7. Communicate with the server
  8. Close the socket to sever the connection.
If UDP is chosen, both communicating applications behave in the same way. In fact it is common to sue exactly the same program running in exactly the same way for both sides of the communications. Each sets itself up on a particular port; it can use that port to transmit to any UDP application anywhere, and it can receive data from any UDP application on that same port.

Stages for a UDP application (see UDP Sample Program):
  1. Create an Internet Datagram socket
  2. Create a sockaddr_in object stating the port number that should be listened to, and the kind of connections to be accepted
  3. Bind the socket to its port
  4. Either wait for an incoming message or send an outgoing message, repeatedly.
    To send an outgoing message:
    1. Look up the IP address of the other system
    2. Create a object stating the IP address and port number for the remote application
    3. Use sendto to send the message
  5. To wait for and receive and incoming message:
    1. Create an empty sockaddr_in object to receive the IP and port numbers of the sender
    2. Provide an array (or other area of memory) to receive data into
    3. Call recvfrom
  6. To terminate communications, close the socket
UDP ports and TCP ports are not the same things. A program can be using TCP port number 1234, and another program can be using UDP port number 1234 on the same computer at the same time without any problems.





Port Numbers

        There is no convenient human-understandable way to refer to internet-enabled applications running on a computer like there is for files. Files have names that can be very descriptive, and have protections and a record of ownership so they can not be subverted for illicit uses. There is nothing like that for internet connections.

A program wishing to receive data over the network (usually a server) must attach itself to an internet port. Other programs wishing to communicate with it must know which port it is attached to. Ports are referred to solely by 16-bit numbers (range 1 to 65535, or 1 to 32767 on some computers). If a program is to communicate with another over the internet, it must know two things: the IP address, (which at least has a memorable human-oriented form, like rabbit.eng.miami.edu) and the port (which is just a meaningless number).

To prevent unconquerable confusion, well-known services always attach themselves to particular well-known port numbers (e.g. web servers use port 80, the mail server uses port 25, and ftp uses port 21). For new or non-famous programs, there are of course no well-known port numbers, and the port number must be treated as part of the address; it is just as vital as the IP address. Common practice is to attach the port number to the IP address with a colon, for example 129.171.33.6:1234 or rabbit.eng.miami.edu:1234.

There is a significant security problem too. At any time that the mail server is not running, another program could attach itself to port 25, and it would receive all incoming mail destined for that computer. The same goes for port 80: another program could pretend to be the web server and provide false information (even falser than the information normally found on the web, that is). The only slight attempt to fix this problem is that on some systems (unixes particularly), all port numbers less than 1024 are accessible only by system (root) processes. So a normal user can't take over one of the well-known port numbers. But there is nothing you can do to protect the port number that your new or non-famous application has decided to use. This is why all secure applications must use some form of encryption on all data sent over the internet, even if they use TCP with "secure" sockets.

UDP and TCP ports are independent: one application can use TCP port 1234, and another can use UDP port 1234 at the same time without problems. However, well-known port numbers are usually kept consistent. For example, DNS runs over both TCP and UDP, and uses both port 53s.

Well-Known Port Numbers from
RFC923
Most computers do not run most of these services, some because they are not useful, but many because they are believed to constitute security risks.
      5        RJE        Remote Job Entry                
      7        ECHO       Echo                              
      9        DISCARD    Discard - Ignore all incoming data
      11       USERS      List Active Users       
      13       DAYTIME    Respond with time of day      
      15       NETSTAT    Who is up or NETSTAT     
      17       QUOTE      Quote of the Day          
      19       CHARGEN    Character Generator        
      20       FTP        File Transfer [Default Data]   
      21       FTP        File Transfer [Control]      
      23       TELNET     Telnet                       
      25       SMTP       Simple Mail Transfer         
      27       NSW-FE     NSW User System FE        
      29       MSG-ICP    MSG ICP                    
      31       MSG-AUTH   MSG Authentication      
      35                  any printer server         
      37       TIME       Time                          
      39       RLP        Resource Location Protocol    
      41       GRAPHICS   Graphics                       
      42       NAMESERVER Host Name Server              
      43       NICNAME    Who Is                       
      44       MPM-FLAGS  MPM FLAGS Protocol              
      45       MPM        Message Processing Module [recv]  
      46       MPM        MPM [default send]               
      47       NI-FTP     NI FTP                         
      49       LOGIN      Login Host Protocol                
      51       LA-MAINT   IMP Logical Address Maintenance      
      53       DOMAIN     Domain Name Server                 
      55       ISI-GL     ISI Graphics Language            
      57                  any private terminal access      
      59                  any private file service          
      61       NI-MAIL    NI MAIL                        
      63       VIA-FTP    VIA Systems - FTP              
      69       TFTP       Trivial File Transfer        
      71       NETRJS     Remote Job Service           
      72       NETRJS     Remote Job Service            
      73       NETRJS     Remote Job Service              
      74       NETRJS     Remote Job Service           
      75                  any private dial out service        
      77                  any private RJE service            
      79       FINGER     Finger                          
      81                  HOSTS2 Name Server              
      83       HOSTS2-NS  MIT ML Device                          
      85       MIT-ML-DEV MIT ML Device                  
      87       MIT-ML-DEV Any Private Terminal Link      
      89       SU-MIT-TG  SU/MIT Telnet Gateway         
      91       MIT-DOV    MIT Dover Spooler              
      93       DCP        Device Control Protocol        
      95       SUPDUP     SUPDUP                         
      97       SWIFT-RVF  Swift Remote Vitural File Protocol 
      99       METAGRAM   Metagram Relay                    
      101      HOSTNAME   NIC Host Name Server             
      105      CSNET-NS   Mailbox Name Nameserver      
      107      RTELNET    Remote Telnet Service          
      109      POP        Post Office Protocol            
      111      SUNRPC     SUN Remote Procedure Call      
      113      AUTH       Authentication Service          
      115      SFTP       Simple File Transfer Protocol     
      117      UUCP-PATH  UUCP Path Service           
      243      SUR-MEAS   Survey Measurement           
      245      LINK       LINK                        






IP Numbers

        IP addresses are simply 32-bit numbers allocated by a central authority to uniquely identify any internet-accessible computer. 32-bit numbers allow for 4,294,967,296 different addresses (but due to allocation inefficiencies there are far fewer than this to go around), and recently it was decided that that is not enough for the whole world. IP6 is on the horizon, under which IP addresses will be 48-bit numbers, but for now 32 bits is all we have to deal with.

Large numbers are hard for people to deal with accurately, so just as in all sensibly regulated human affairs (miles, feet, and inches, or stones, pounds, and ounces, or pounds, shillings, and pence) IP numbers are split into reasonably-sized components. The notation 129.171.33.6 really represents a base-256 number, equal to 129*256^3 + 171*256^2 + 33*256 + 6.

The more human-oriented form of IP addresses, e.g. rabbit.eng.miami.edu is directly translated into the corresponding IP number by a service called DNS (Domain Name Service), which programs can access through the
gethostbyname system function. The verbal form should be used whenever possible, as it is much less likely to change than the numeric form.

The numeric form A.B.C.D is actually two numbers concatenated. rabbit.eng.miami.edu refers to the host (i.e. computer) called rabbit in the domain called eng.miami.edu. The corresponding numeric form is 129.171.33.6, in which 129.171 represents miami.edu, and 33.6 represents rabbit.eng. Large domains are often split up into sub-domains (that is how 129.171 manages to represent miami.edu rather then eng.miami.edu; eng.miami.edu is a subdomain in miami.edu). sub-domains are not required to be represented by a consistent part of the IP number: 129.171.33 is not the designation for eng.miami.edu.

The division between domain and host in an IP number is easy to determine. Given the IP number A.B.C.D:





Byte Order

        Different computers store their integers in different ways. Some (including Intel-based PCs and Vaxes) make the rational choice of storing the least significant bytes first (at the lowest addresses), which is called the Little Endian order. Some make the less rational choice of storing the most significant byte first: Big Endian, while a very few are completely irrational and follow something like the firing order of a four cylinder car engine. The following C++ program shows how byte-order can be seen:
#include <stdio.h>
#include <sys/param.h>   

union converter
{ struct { unsigned char a, b, c, d; } b;
  int i; };

void main(void)
{ converter c;
  printf("&int=%u; &byte-a=%u; &byte-d=%u\n", &c.i, &c.b.a, &c.b.d);
  c.i=0x11223344;
  printf("%08X = %02x-%02X-%02X-%02X\n", c.i, c.b.a, c.b.b, c.b.c, c.b.d); }
        The union type called converter arranges for one int and four bytes to share the same memory, so using a variable c of type converter, storing an integer in c.i allows the individual bytes of that integer to be seen in c.b.a, c.b.b, c.b.c, and c.b.d. The program first prints the addresses of c.i, c.b.a, and c.b.d to confirm that the compiler has not reordered things, and byte a is indeed the first byte and d is the last. Then it stores a hexadecimal constant in c.i (hexadecimal makes the individual bytes obvious), you can see that the most significant byte is 0x11, and the least significant byte is 0x44. When this program is run on an intel-86-based computer, you should see this output: 11223344 = 44-33-22-11, confirming that the least significant byte is stored first.

        Byte order is rarely relevant unless two computers of different types have to communicate, and that is what the internet is all about. Integers that describe network addresses must be in a single consistent format regardless of the kind of computer currently in use. The network format for integers happens to be Big Endian. Programs that deal with IP addresses have to be able to convert from one form to the other. The functions htonl and ntohl convert 32-bit values (i.e. IP addresses); htons and ntohs convert 16-bit values (i.e. port numbers). In those four names, 'h' stands for 'host' (the computer you're using), 'to' is 'to', 'n' stands for 'network', 's' is for 'short', and 'l' is for 'long', so htonl converts a 32-bit int from the computer's format to the network format.

        An extended version of the above program shows the function htonl is action. On most computers ntohl and htonl are indentical.
#include <stdio.h>
#include <sys/param.h>   

union converter
{ struct { unsigned char a, b, c, d; } b;
  int i; };

void main(void)
{ converter c;
  printf("&int=%u; &byte-a=%u; &byte-d=%u\n", &c.i, &c.b.a, &c.b.d);
  c.i=0x11223344;
  printf("%08X = %02x-%02X-%02X-%02X\n", c.i, c.b.a, c.b.b, c.b.c, c.b.d);
  c.i=htonl(c.i);
  printf("htonl\n");
  printf("%08X = %02x-%02X-%02X-%02X\n", c.i, c.b.a, c.b.b, c.b.c, c.b.d);
On a PC or Vax, the output should be 11223344 = 44-33-22-11; htonl; 44332211 = 11-22-33-44.
On a Big-endian computer, it should be 11223344 = 11-22-33-44; htonl; 11223344 = 11-22-33-44.

Of course, under IP6 when IP addresses are 6-byte values, everything will become more complicated.

(The terms Big-Endian and Little Endian come from Jonathan Swift's 1726 satire Gulliver's Travels, in which the terms named the opposing sides in a theological war. One side believed that boiled eggs should be eaten little-side up, and the other side believed the opposite.)





gethostbyname, inet_ntoa: Simple Sample Program (C++)

This shows only the most useful aspects of
gethostbyname; it shows how to find the IP address (in a form suitable for making connections) associated with any reasonable form of a computer's name, such as "rabbit.eng.miami.edu", "rabbit", or "129.171.33.6".
#include <stdio.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h> 
#include <arpa/inet.h>

void main(void)
{ hostent * record = gethostbyname("rabbit.eng.miami.edu");
  if (record==NULL)
  { herror("gethostbyname failed");
    exit(1); }
  in_addr * address=(in_addr * )record->h_addr;
  printf("IP Address: %s\n", inet_ntoa(* address)); }





gethostbyname: Full Sample Program (C++)

This shows everything that can be done with the result of
gethostbyname. Most of this is not very useful, a more realistic sample is given above.
#include <stdio.h>
#include <netdb.h>
#include <unistd.h>        // only needed for definition of gethostname for part 1
#include <netinet/in.h>    // only needed for section 8
#include <arpa/inet.h>     // only needed for section 8
#include <sys/socket.h>    // only needed for definition of AF_INET for part 5
#include <sys/param.h>     // only needed for definition of MAXHOSTNAMELEN for part 1

void main(int argc, char *argv[])
{ 
  // Part 1 (optional) get the name that is to be looked up
  char hostname[MAXHOSTNAMELEN];
  if (argc==2)
    strcpy(hostname, argv[1]);
  else
    gethostname(hostname, MAXHOSTNAMELEN);
  
  // Part 2 (required)
  hostent * record = gethostbyname(hostname);
  if (record==NULL)
  { herror("gethostbyname failed");
    exit(1); }

  // Part 3 (optional) The official name may not be the same as the parameter
  printf("Official name: %s\n", record->h_name);

  // Part 4 (optional) Some names have a list of alternative forms
  for (int i=0; 1; i+=1)
  { if (record->h_aliases[i]==NULL) break;
    printf("Alternate name: %s\n", record->h_aliases[i]); }

  // Part 5 (optional) Make sure it really is an internet address
  if (record->h_addrtype==AF_INET)
    printf("Internet Address\n");
  else
    printf("Other (non-internet) Address\n");

  // Part 6 (optional) Find out what size the address is (4 bytes), may be come 6 one day
  int len=record->h_length;
  printf("Address length = %d\n", record->h_length);

  // Part 7 (optional) Illustrates the internal format of an IP address
  char * addr=record->h_addr;
  printf("Main Address: ");
  printf("%d", (unsigned char)addr[0]);
  for (int i=1; i<len; i+=1)
    printf(".%d", (unsigned char)addr[i]);
  printf("\n");

  // Part 8 (useful)
  in_addr * address=(in_addr * )record->h_addr;
  printf("Main Address: %s\n", inet_ntoa(* address));

  // Part 9 (optional) Illustrates obtaining IP as an int
  int ip = ntohl(address->s_addr);
  printf("Main Address: %d.%d.%d.%d\n", (ip>>24)&0xFF, (ip>>16)&0xFF, (ip>>8)&0xFF, ip&0xFF);

  // Part 10 (optional) Print any secondary IP addresses
  //               note loop starts at 1 because h_addr = h_addr_list[0]
  for (int i=1; 1; i+=1)
  { in_addr * address = (in_addr *)record->h_addr_list[i];
    if (address==NULL) break;
    printf("Address: %s\n", inet_ntoa(* address)); } }






Sample Internet (IP+TCP) Server Program (C++)

This server waits for a client to connect to it, then sends a single "hello..." line to the client, and closes the connection. The communications in this program are all one-way, the server never pays any attention to input from the client, but that is a trivial thing to change.

It expects to be given a port number on the command line. Remember that numbers below 1024 are reserved on many systems. When the server is running on computer X, port Y, it can be tested with the command "telnet X Y", or using the
sample client.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>

extern int errno;

void main(int argc, char *argv[])
{ 
  // get port number to serve from command line
  if (argc!=2)
  { fprintf(stderr, "no port number\n"); exit(1); }
  int port_number = atol(argv[1]);

  // Step 1 create a socket
  int main_socket = socket(AF_INET, SOCK_STREAM, 0);
  if (main_socket<0) { perror("socket creation"); exit(1); }

  // Step 2 create a sockaddr_in to describe the service
  sockaddr_in server_info;
  server_info.sin_len = sizeof(server_info);
  server_info.sin_family = AF_INET;
  server_info.sin_addr.s_addr = htonl(INADDR_ANY);
  server_info.sin_port = htons(port_number);

  // Step 3 use bind to set the socket according to the sockaddr_in
  int r1 = bind(main_socket, (sockaddr *) &server_info, sizeof(server_info));
  if (r1<0) { perror("port in use"); exit(1); }

  // Step 4 use listen to turn the server on
  int r2 = listen(main_socket, 3);
  if (r2<0) { perror("listen"); exit(1); }
  printf("Listening on port %d\n", port_number);  

  // Servers usually accept multiple clients, so a loop is used
  int session_number=0;
  while (1)
  { 
    // Step 5 set up another sockaddr_in to receive information on the client
    sockaddr_in client_info;
    unsigned int client_info_size = sizeof(client_info);
    
    // Step 6 use accept to wait for and accept the next client
    int session_socket = accept(main_socket, (sockaddr *) &client_info, &client_info_size);
    if (session_socket<0)
    { if (errno==EINTR) continue;  // EINTR is not a problem
      perror("accept");
      usleep(100000); 
                         // Other errors are probably a reason to stop, but for a robust server
                         // just give the error a chance to go away and try again
      continue; }
    session_number+=1;

    // At this point, a heavy-duty server would use fork to create a sub-process, and
    // let the sub-process deal with the client, so we can wait for other clients.

    // accept filled in the provided sockaddr_in with information on the client
    char * who_is_it = inet_ntoa(client_info.sin_addr);
    printf("[connection %d accepted from %s]\n", session_number, who_is_it);
  
    // Step 7 (Optional) Create normal files for communication with the client
    //        Or just use read and write directly on the session_socket itself
    FILE * r_connection=fdopen(session_socket, "r");
    FILE * w_connection=fdopen(session_socket, "w");

    // Step 8 Deal with the client
    fprintf(w_connection, "Hello, %s\r\n", who_is_it);

    // Step 9 When finished send all lingering transmissions and close the connection.
    fflush(w_connection);
    fclose(w_connection);
    fclose(r_connection);   
    close(session_socket); } }






Sample Internet (IP+TCP) Client Program (C++)

This client expects an computer name and port number on the command line; the basic version (without step 6) connects to the indicated server, then just prints whatever the server sends. Communications are entirely one-way: the client never transmits anything, so it can only usefully connect to servers that never listen. The best way to test it is with the
Sample Server

If the two extra lines shown as the optional step 6 are included in the program, it acts as a text-only web browser. After connecting to the server, it sends a simple HTTP request for its main index.html page, and prints out whatever is received. This version doesn't need any special server to test it, any available web server will do, e.g. "a.out rabbit.eng.miami.edu 80"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

void main(int argc, char *argv[])
{ 
  // get server IP address and port number of server from command line
  if (argc!=3)
  { fprintf(stderr, "no address and port\n"); exit(1); }
  char * server = argv[1];
  int port_number = atol(argv[2]);

  // Step 1 Look up server to get numeric IP address
  struct hostent * record = gethostbyname(server);
  if (record==NULL) { herror("gethostbyname failed"); exit(1); }
  struct in_addr * addressptr = (in_addr *) record->h_addr;

  // Step 2 create a socket
  int main_socket = socket(AF_INET, SOCK_STREAM, 0);
  if (main_socket<0) { perror("socket creation"); exit(1); }

  // Step 3 create a sockaddr_in to describe the server
  struct sockaddr_in server_info;
  server_info.sin_len = sizeof(server_info);
  server_info.sin_family = AF_INET;
  server_info.sin_addr = * addressptr;
  server_info.sin_port = htons(port_number);

  // Step 4 connect
  int r = connect(main_socket, (struct sockaddr *) &server_info, sizeof(server_info));
  if (r<0) { perror("connect"); exit(1); }
  printf("Connected to %s\n", inet_ntoa(* addressptr));

  // Step 5 (Optional) Create normal files for communication with the client
  //        Or just use read and write directly on the session_socket itself
  FILE * r_connection=fdopen(main_socket, "r");
  FILE * w_connection=fdopen(main_socket, "w");

  // Step 6 (Optional, for web servers only)
  //        Only include the following two lines when connecting to a web server
  fprintf(w_connection, "GET /index.html HTTP/1.0\r\n\r\n");
  fflush(w_connection);

  // Step 7 Deal with the client
  char line[1000];
  for (int i=1; 1; i+=1)
  { char *s=fgets(line, 999, r_connection);
    if (s==NULL)
    { printf("Disconnected\n");
      break; }
    printf("Line %d: %s", i, line); }

  // Step 8 When finished send all lingering transmissions and close the connection
  fflush(w_connection);
  fclose(w_connection);
  fclose(r_connection);   
  close(main_socket); }






Sample IP+UDP Communications Program (C++)

This client expects three things on the command line: the port it should listen on, the remote computer it should send to, and the port on that remote computer.

The program immediately sends a string to the indicated computer+port, then waits for a single message from anywhere, then sends a second string to the original computer+port again, before exitting. Because UDP just shouts into the wind, and does not guarantee delivery, you should not expect to see all the messages.

For example, in one rabbit session type "a.out 1234 rabbit.eng.miami.edu 1235"; The program immediately sends "hello you" to port 1235 (where nothing is listening yet) then waits for incoming messages. Next, in another session, type the similar but different "a.out 1235 rabbit.eng.miami.edu 1234"; here the program will immediately send "hello you" to port 1234, where it is received by the first session and printed. It then waits for incoming messages on port 1235. The first session then sends its second message "hello again" to port 1235 and exits. The second session receives and prints "hello again", then proceeds to send "hello again" to port 1234 where nothing is listening before exitting. So although four messages are sent, only two are received and printed, one saying "hello you" and the other "hello again".
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

void main(int argc, char *argv[])
{ 
  // get port to run on, and IP+port to communicate with from command line
  if (argc!=4)
  { fprintf(stderr, "requires localport remoteip remoteport\n"); exit(1); }
  int port_number = atol(argv[1]);
  char * remote = argv[2];
  int remote_port = atol(argv[3]);

  // Step 1 Look up server to get numeric IP address
  struct hostent * record = gethostbyname(remote);
  if (record==NULL) { herror("gethostbyname failed"); exit(1); }
  struct in_addr * addressptr = (in_addr *) record->h_addr;

  // Step 2 Create a socket
  int main_socket = socket(AF_INET, SOCK_DGRAM, 0);
  if (main_socket<0) { perror("socket creation"); exit(1); }

  // Step 3 Create a sockaddr_in to describe the local port
  struct sockaddr_in local_info;
  local_info.sin_len = sizeof(local_info);
  local_info.sin_family = AF_INET;
  local_info.sin_addr.s_addr = htonl(INADDR_ANY);
  local_info.sin_port = htons(port_number);

  // Step 4 Bind the socket to the port
  int r = bind(main_socket, (struct sockaddr *) &local_info, sizeof(local_info));
  if (r<0) { perror("bind"); exit(1); }
  printf("ready\n");

  // Step 5 Create a sockaddr_in to describe the remote application
  struct sockaddr_in remote_info;
  remote_info.sin_len = sizeof(remote_info);
  remote_info.sin_family = AF_INET;
  remote_info.sin_addr = *addressptr;
  remote_info.sin_port = htons(remote_port);

  // Step 6 Send a message
  char *message1="Hello you\n";
  r=sendto(main_socket, message1, strlen(message1), MSG_EOR,
               (struct sockaddr *) &remote_info, sizeof(remote_info));
  if (r<0) { perror("sendto"); exit(1); }
  printf("sent %d characters of %s\n", r, message1);

  // Step 7 Wait for a message to be received
  char buffer[100];
  struct sockaddr_in incoming_info;
  unsigned int socklen = sizeof(incoming_info);
  r=recvfrom(main_socket, &buffer, sizeof(buffer)-1, 0,
             (struct sockaddr *) &incoming_info, &socklen);
  if (r<0) { perror("recvfrom"); exit(1); }
  buffer[r]=0;
  printf("from %s port %d, %d characters: %s\n",
                  inet_ntoa(incoming_info.sin_addr), 
                  ntohs(incoming_info.sin_port),
                  r,
                  buffer);

  // Duplicate for step 6, but with a different message
  char *message2="Hello again\n";
  r=sendto(main_socket, message2, strlen(message2), MSG_EOR,
           (struct sockaddr *) &remote_info, sizeof(remote_info));
  if (r<0) { perror("sendto"); exit(1); }
  printf("sent %d characters of %s\n", r, message2);

  // Step 8 Close the socket and exit
  close(main_socket); }