Berkeley Sockets & TCP UDP Code

Embed Size (px)

DESCRIPTION

It's about Berkley Sockets

Citation preview

  • The Transport Layer in TCP/IP stackTCP layerChapter 6

  • The Transport ServiceServices Provided to the Upper LayersTransport Service PrimitivesBerkeley SocketsAn Example of Socket Programming: An Internet File Server

  • Services Provided to the Upper LayersThe network, transport, and application layers.

  • Attributes of TCP layer in TCP/IPThe entity which implements TCP functionality is called TRANSPORT ENTITY. It talks to other similar entity by sending a TPDU packet via IP layer.It can be implemented in OS kernel, in network library function, in a user space or in firmware of a Network Interface Card.It provides efficient, reliable and cost-effective service to application layer.It uses services provided by IP (lower) layer and does not duplicate the same here.

  • Attributes of TCP layer in TCP/IP(2)It provides CO and CL types of services primarily for data-transfer. It also provides a method of directly calling functions of IP layer.It takes care of addressing, flow control and error-free transportation between two end points.TCP code runs mostly on host machines while lower 3 layers may run on switching equipment like routers and link switches.It covers all the short comings of network layer by backing up or wrapping up it with its own superior code.

  • Attributes of TCP layer in TCP/IP(3)Suppose during a file transfer in a CO connection, the failure occurs after half of records have been sent, TCP may open extra connection and enquire which record need to be resent, and send it and make up for loss.Lost or mangled packets are compensated by TCP layer code.It hides a variety of networks in lower layers wireless or wireline and thus to the application layer, it offers a smooth seamless uniform experience.

  • Transport Service PrimitivesThe primitives for a simple hypothetical transport service.LISTEN is for servers to create a socket and listen for clients arrival.CONNECT is for client to make a connection request.SEND, RECEIVE and DISCONNECT is for both client and server.

  • Transport Service Primitives (2)The nesting of TPDUs, packets, and frames.TPDU payload is message given by Application layer.TCP adds TPDU header, IP adds Packet Header and Data Link adds Frame Header to it send it to other machine.

  • Transport Service Primitives (3)A state diagram for a simple connection management scheme. Transitions labeled in italics are caused by packet arrivals. The solid lines show the client's state sequence. The dashed lines show the server's state sequence.

  • Transport Service Primitives (4)Notes:Initially both client and Server are in off state and they switch ON.Server starts the process by executing LISTEN and blocks in IDLE state.Client sends CONNECT TPDU and blocks in ACTIVE ESTABLISHMENT PENDING state . Server receives it, responds to it and enters PASSIVE ESTABLISHMENT PENDING state and sends matching acknowledgement TPDU to client and enters ESTABLISHED state. Client receives it and enters ESTABLISHED state. Both now SEND or RECEIVE data in both directions many times.Disconnection can be initiated by any of the two. The one who initiates it sends DISCONNECT TPDU and enters ACTIVE or PASSIVE DISCONNECT PENDING STATE.The receiver sends acknowledgement TPDU to initiator and enters IDLE state. The initiator receives acknowledgement and enters IDLE state.

  • Berkeley SocketsThe socket primitives for TCP.UNIX provided by UC Berkeley provided these service primitives or verbs or functions in C at kernel level.They offer more flexibility and facility than primitives we discussed.we are going to write code to use them and our code will behave like application layer programs.First 4 primitives are used by server, fifth by only client and rest 3 by both.

  • Berkeley Sockets ..SOCKET primitiveThis primitive is used by Server only.This creates a new end point and allocates memory space for creating Transport entity. It specifies parameters as:Family: PF_INET (IPv4 type) or PF_INET6 (IPv6 type internet).Type of socket: SOCK_STREAM for TCP, SOCK_DGRAM (for UDP), SOCK_SeqPACKET for STCP, SOCK_RAW (for services using IP services directly).Protocol: Set to 0 since this is only one protocol at this layer.Local Socket Address: Data Structure containing fields- local host port no (process) , local host IP address and family ( AF_INET). Remote Socket Address: Same as above except that it is for remote host.

  • Berkeley Sockets ..SOCKET primitive

    When this call is successful it returns a File Descriptor (fd1) or socket id which is of type integer. This will be used in all future socket commands as an identifier or address to which each primitive command will be directed. When a socket is closed, this identifier perishes.In newly created socket, the address fields are empty. These will be filled up with server or client addresses at appropriate time.

  • Berkeley Sockets ..BIND primitiveThis primitives assigns server addresses to socket to which remote clients will connect to.Client addresses are not yet known since client has not arrived yet so its identity is not known.SOCKET and BIND create a first level socket popularly called as listen socket. This socket will listen to arrival of client requests. This will not be used for data transfer. It returns 0 as success and -1 as failure.

  • Berkeley Sockets ..LISTEN primitiveThis primitives allocates queue space in memory for remote hosts or clients to queue up to be serviced. It also starts server process to check and accept client requests.If the queue size specified is 1 then first client will be connected. While first client is interacting with server, if second client attempts to make a connection, it will fail.

  • Berkeley Sockets ..LISTEN primitive (2)If the queue length specified is more than 1 then second client will be put in a queue and will block pending connection.The server does not blocks on this call until a client requests a connection. Blocking will come later with next primitive.We need to call this primitive often to empty the queue.It returns 0 as success and -1 as failure.

  • Berkeley Sockets ..ACCEPT primitiveThis primitive causes server to block waiting for a connection request to arrive from client.Once the connection request TDPU from a client arrives, server unblocks, creates a new socket with same properties and new identifier and returns that as a new file descriptor say fd2 which will be used for read/write operations with the first client.Note that old socket fd1 will be used for further listening on new clients while new socket fd2 will be used for currently connected client data transfer. When we close the connection with current client then fd2 will perish but fd1 will continue to exist.

  • Berkeley Sockets ..ACCEPT primitiveThe client identity is now known and now clients address data is filled up in sockets client address structure.The server can then fork off to create another process or thread to handle the new connection for original socket. Each time, it connects to one new client from queue, it will spawn a new socket (fd3, fd4 etc.) to handle it and maintain old socket (fd1) to service next in queue. First 4 primitives are for server only. Executing all 4 completes connection phase.It returns 0 as success and -1 as failure.

  • Berkeley Sockets ..CONNECT primitiveThis primitive causes client to send a request TPDU to sever, and then to block waiting for a connection request acknowledgement or confirmation to arrive from server.BIND primitive is not needed at client because client always knows its own address as well as servers address and that is fully specified in this primitive.Once the acknowledgement TDPU from server arrives, client unblocks, and connection is established.Now client and server can both send or receive the data to each other.It returns 0 as success and -1 as failure.

  • Berkeley Sockets.. SEND RECEIVE & CLOSE primitivesThese 3 primitives are common to both server and client. SEND primitive is implemented as write command while RECEIVE is invoked as read command.Both commands use 3 arguments- fd, buffer_label and number_of_bytes to be transferred. read and write both return the actual number of bytes transferred and we need to put them in infinite loop until the whole array is transferred.CLOSE is symmetric i.e., it can be started by any one of the two hosts. Once both sides execute it and exchange packets, the resources for socket are released.

  • Data Transfer PrimitivesThe basic purpose of establishing a connection is to transfer data. The primitives are available to send or receive the data in a array whose length can be set by calling function. So to send just a character, we can set the length to 1 byte.The Berkeley primitives are read and write.However, we can also use send()andrecv() orsendto()andrecvfrom() for sending and receiving data to/from a remote socket.One should check the version of OS or TCP/IP library about, which of the above pair is available for data transfer and what is its precise syntax.

  • TCP SOCKET FLOW DIAGRAM

  • Sample code for TCP Client & ServerWe will now study how to do socket programming.On client side the code will use socket(), connect(), read (),write()and close() functions or primitivesOn server side we will use socket() for passive open followed by Bind(), then Listen() and finally accept() primitivesAfter that we will use read/write functions and may or may not close the socket.It will be very important to study how the data structure for storing IP and port no and other parameters are declared and used.

  • TCP Client Code - Create a socket

    This first thing to do is create a socket. Thesocketfunction does this. #include#include int main(int argc , char *argv[]){int fd1;fd1 = socket(AF_INET , SOCK_STREAM , 0);if (fd1 == -1) {printf("Could not create socket");}return 0;}

  • TCP Client Code - Create a socket (2)Function socket() creates a socket and returns a descriptor fd1 which can be used in other functions. The above code will create a socket with following properties:Address Family - AF_INET (this is IP version 4) Type - SOCK_STREAM (this means connection oriented TCP protocol) Protocol - 0 or IPPR

    We will now connect to a remote server on a certain port number. So we need 2 things,server IP addressandPort numberto connect to.To connect to a remote server we need to do a couple of things. First is to create a sockaddr_in structure with proper values.

  • TCP Client Code - Socket Data StructureIn Berkeley sockets it is defined as sockaddr_instruct sockaddr_in { short sin_family; // e.g. AF_INET, AF_INET6 unsigned short sin_port; // e.g. htons (3490) struct in_addr sin_addr; // see struct in_addr, below char sin_zero[8]; // zero this if you want to};struct in_addr { unsigned long s_addr; // load with inet_pton()// the address stored here is a 32-bit IP address derived from// human readable form like 192.168.1.2};

  • Some explanation..(2)The sockaddr_in has a member called sin_addr of type in_addr which has a s_addr which is nothing but a long. It contains the IP address in long format.

    Functioninet_addris a very handy function to convert an IP address to a 32-bit long format. See code below:

  • Endianness

    The termsendianandendiannessrefer to theconventionused to interpret the bytes making up a datawordwhen those bytes are stored incomputer memory.Big-endiansystems store themost significant byteof a word in thesmallest addressand the least significant byte is stored in the largest address. (IBM)Little-endiansystems, in contrast, store theleast significant bytein the smallest address.(Intel)Big-endian is the most common convention in data networking (includingIPv4 or IPv6), hence its pseudo-synonymnetwork byte order, and little-endian is popular (though not universal) among microprocessors in part due to Intel's significant historical influence on microprocessor designs.

  • Conversion from one notation to otherFollowing functions are used to convert from h (host) to n (network) or vice versa. S is for short or 16 bit number i.e. for converting Port No. L is for long or 32 bit number for converting IP address.

    htons() ; // hosttonetworkshorthtonl(); // hosttonetworklongntohs();// networktohostshortntohl(); //networktohostlong

  • Some explanation..#include #include

    unsigned short htons(unsigned short host_short)

    Thehtons()function is used to convert a short (2-byte) integer from the local host byte order to standard network byte order.

    host_short(Input) The 2-byte integer in local host byte order that is to be converted to standard network byte order.

    Return Valuehtons()returns an integer. Possible values are:n (where n is the 2-byte integer in standard network byte order)

  • TCP Client code to connect to server// set up servers parameters before connect is executed.server.sin_addr.s_addr = inet_addr("74.125.235.20");// IP address setserver.sin_family = AF_INET; server.sin_port = htons( 3490 );//// Port No. set//Connect to remote server, see pointer typecasting.if (connect(fd1 , (struct sockaddr *) &server , sizeof(server)) < 0){puts("connect error");return 1;}puts("Connected");return 0;}

  • TCP Client Code - send data over socket

    Functionsend()will simply send data. It needs the socket descriptor fd1, the data to send and its size. Here is a very simple example of sending some data to server://Send some datachar *message = Hello From Client To Server";if( send(fd1 , message , strlen(message) , 0) < 0){puts("Send failed");return 1;}puts("Data Sent\n");

  • TCP Client Code receive data over socketFunctionrecv() is used to receive data on a socket. In the following example we expect the echo server to echo back same number of characters as sent with just incrementing each character by 1://Receive a reply from the serverchar *server_reply[100];if( recv(fd1, server_reply , strlen(message) , 0) < 0){puts("recv failed"); }puts("Reply received\n");puts(server_reply);// print received character string.// We can also use read() as follows:read(fd1, server_reply , strlen(message));

  • TCP Close socket

    Functioncloseis used to close the socket. Need to include the header file for this. That is all for client side.

    close(fd1);

  • TCP Server code - create a socket

    This first thing to do is create a socket. Thesocketfunction does this. #include#include int main(int argc , char *argv[]){int fd1, fd2, c;// fd2 and c will be used later. struct sockaddr_in server;fd1 = socket(AF_INET , SOCK_STREAM , 0);if (fd1 == -1) {printf("Could not create socket"); }}

  • TCP Server code create address structure

    The bind function can be used to bind a socket to a particular "address and port" combination. It needs a sockaddr_in structure similar to connect function.

    //Prepare the sockaddr_in structureserver.sin_family = AF_INET;server.sin_addr.s_addr = INADDR_ANY;server.sin_port = htons( 3490);// INADDR_ANY means client IP is not important// for socket connection, any client IP will do.

  • TCP Server code bind a socket

    The bind function usage is here://Bindif( bind(fd1,(struct sockaddr *) &server , sizeof(server)) < 0){puts("bind failed");}puts("bind done");

  • TCP Server code Listen on the socket

    After binding a socket use functionlistento put the socket in listening mode. //Listenlisten(fd1 , 3); // create space for 3 clients in queue.

  • TCP Server code Accept on the socket

    // This function accepts request by queued client // request. Accept and incoming connectionputs("Waiting for incoming connections...");c = sizeof(struct sockaddr_in);fd2 = accept(fd1, (struct sockaddr *)&client, (socklen_t*)&c);if (fd2

  • TCP Server code what is clients IP?

    // For fun let us print the IP address and port // number of connected client. First convert dotted // representation to 32- bit integer using ntoa. char *client_ip = inet_ntoa(client.sin_addr);// convert network byte order to host byte order,int client_port = ntohs(client.sin_port);printf("\N %d Client IP address is = ",client_ip);printf("\N %d Client Port no is = ",client_port);

  • TCP Server code wait for a char to arrive!

    // connection is made, now wait for incoming character, // increment it and echo it back.char c_in, c_out;// single char input and output buffer.while ( (read(fd2, c_in , 1)

  • TCP Server code read a char and echo it back

    // display received character.printf("%c", c_in);// display it on screenc_out = c_in +1;// increment outgoing char. if( send(fd2, c_out , 1 , 0) < 0) { printf("\n Send failed"); return (-10); }// we are here means send was successful so print sent char // on display.printf("%c",c_out);// display it on screen

  • TCP Server code Now what?Server has waited for a char to come, received it, incremented it and sent it back. It is now up to us to either close the connection of just to be in a finite loop ( do it for 10 characters and then stop) or put this in an infinite loop.

    The choice is ours depending upon what we intend our server to do.

  • TCP Server code A note on receiveNote that receive function reads all the char waiting in socket input buffer and returns value of n i.e. number of bytes read, in a buffer whose address is supplied by us.The value of n could be much less than what we are expecting. So we need to call receive function again and again as given here in this code snippet.

  • TCP Server code Multiple readchar buf[256];// buffer where to store incoming char.int maxLen = sizeof(buf); // maxLen will be 256 initially. char *ptr = buffer;// ptr points to beginning of bufint n = len = 0;// define two temp variables.// read till buf is full or 256 bytes are read.while( (n = recv(fd2, ptr,maxLen,0) ) > 0){// recv has read n char so increment ptr and decrement no // of bytes more to be read.ptr = ptr + n; // increment pointer by n.maxLen = maxLen-n;// decrement number yet to come. len = len + n ;// increment no of bytes recd so far}// the while loop will run till maxLen becomes 0.

  • Socket Programming Example:Internet File ServerClient code using sockets.6-6-1

  • Socket Programming Example:Internet File Server (2)Server code using sockets.

  • Sample code for UDP Client & ServerWe will now study how to do UDP socket programming.On client side the code will use socket(), bind(), sendto() and recvfrom() functions or primitives.On server side we will use socket() for passive open followed by Bind() primitives. After that we will use sendto() and recvfrom() functions or primitives and may or may not close the socket.It will be very important to study how the data structure for storing IP and port no and other parameters are declared and used.Note it is simpler than TCP. See link below:http://www.binarytides.com/programming-udp-sockets-c-linux/

  • UDP SOCKET FLOW DIAGRAM

  • Some interesting differences with TCPThe most important difference is that UDP sockets are not connection oriented. More technically speaking, a UDP server does not acceptconnections and a UDP client does notconnectto server.The server will bind and then directly receive data and the client shall directly send the data.So lets first make a very simple ECHO server with UDP socket. The flow of the code would besocket() -> bind() -> recvfrom() -> sendto()There is only one file descriptor needed in UDP.After one transaction, socket can be closed.

  • UDP Server code Include Files

    This first thing to do is create a socket. Thesocketfunction does this. #include //printf#include //memset#include //exit(0);#include#include

    #define BUFLEN 512 //Max length of buffer#define PORT 8888 //The port no on which to listen for incoming data

  • UDP Server code - create a socketint main(void){// let us first define some variables.struct sockaddr_in server, client; // define two socket structures.int fd, i, recv_len, slen = sizeof(client) ;char buf[BUFLEN];//crate a UDP socket, see the DGRAM parameter.if ( (fd=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){die("socket");// this function is for error handling.}

  • UDP Server code prepare data structure for socket and bind// zero out the structurememset((char *) &server, 0, sizeof(server));// set up parameters for server address fields.server.sin_family = AF_INET;server.sin_port = htons(PORT);server.sin_addr.s_addr = htonl (INADDR_ANY);//bind socket to portif ( bind(fd , (struct sockaddr*)&server, sizeof(server) ) == -1){ die("bind"); }

  • UDP Server code receive first//keep listening for data in infinite loopwhile(1){printf("Waiting for data...");fflush(stdout);// clears output stream to display.//try to receive some data, this is a blocking callif ((recv_len = recvfrom(fd, buf, BUFLEN, 0, (struct sockaddr *) &client, &slen)) == -1){ die("recvfrom()"); }// Note buf, BUFLEN, client and &slen.

  • UDP Server code print it // print details of the client/peer and the data // received printf("Received packet from %s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));

    printf("Data: %s\n" , buf);

  • UDP Server code send next & close //now reply the client with the same data

    if (sendto(fd, buf, recv_len, 0, (struct sockaddr*) &client, slen) == -1){die("sendto()");}

    // Note fd, buf, recv_len, client and slen. Close socket after transaction is done.close(fd);return 0;

  • UDP Client code #include //printf#include //memset#include //exit(0);#include#include#define SERVER "127.0.0.1 // Local Loopback #define BUFLEN 512 //Max length of buffer#define PORT 8888 //The port on which to send data

  • UDP Client code #include //printf#include //memset#include //exit(0);#include#include#define SERVER "127.0.0.1 // Local Loopback #define BUFLEN 512 //Max length of buffer#define PORT 8888 //The port on which to send data

    void die(char *s){perror(s); exit(1); }

  • UDP Client code Create socketstruct sockaddr_in server;int fd, i, slen=sizeof(server);char buf[BUFLEN];char message[BUFLEN];if ( (fd=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){die("socket");}

  • UDP Client code socket structure // fill zeroes and set parameters for bind.memset((char *) &server, 0, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(PORT);

    // SERVER loopback number is stored in server.sin_addrif (inet_aton(SERVER , &server.sin_addr) == 0) {fprintf(stderr, "inet_aton() failed\n");exit(1);}// client is ready to transact data with server.

  • UDP Client code Send messagewhile(1)// we can put read write in infinite loop.{printf("Enter message : ");gets(message);// get message from keyboard.//send the message to server in same PC.if (sendto(fd, message, strlen(message) , 0 , (struct sockaddr *) &server, slen)==-1){die("sendto()");}

  • UDP Client code Receive message//receive a reply and print it. clear the buffer by filling// null, it might have previously received data.memset(buf,'\0', BUFLEN);//try to receive some data, this is a blocking callif (recvfrom(fd, buf, BUFLEN, 0, (struct sockaddr *) &server, &slen) == -1){die("recvfrom()");}puts(buf);// print data echoed from server.} // end of infinite loopclose(fd);return 0;