Unix Socket Programmgin

  • May 2020
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Unix Socket Programmgin as PDF for free.

More details

  • Words: 2,162
  • Pages: 33
A SOCKET IS BASICALLY ADDRESS + PORT SOCKET INIP UNIX NO.NOW everything in Unix is a file!”

when Unix programs do any sort of I/O, they do it by reading or writing to a file descriptor.A file descriptor is simply an integer associated with an open file.So when you want to communicate with another program over the Internet you're gonna do it through a file descriptor.To get a file descriptor for network communication You make a call to the socket()system routine. It returns the socket descriptor, and you communicate through it using the special-

What is a socket? Socket: An interface between an application process and transport layer The application process can send/receive messages to/from another application process (local or remote)via a socket In Unix , a socket is a file descriptor . an integer associated with an open file Types of Sockets: stream sockets,datagram sockets. Internet sockets characterized by IP Address (4 bytes) and port number (2 bytes)

Types of Internet Sockets Stream Sockets (SOCK_STREAM) Connection oriented Rely on TCP to provide reliable two way connectedcommunication Datagram Sockets (SOCK_DGRAM) Rely on UDP Connection is unreliable

Socket Description

Client-server interaction

The entire client-server operation

This client-server progs are working on following principles:

The server is listening and waiting for a connection from the client.these server can process 10 clients by using child processes for each new client. When the client connects to the server the server creates a new file descriptor using accept() and creates a new child process using fork() Now using send() the server sends a “ Hello,World!” message to the client which is accepted by the client using recv() Now the client displays this “Hello,World!” message on the screen If there is a error in any of these processes than a error message is displayed

Basic server operation

Often, there will only be one server on a machine, and that server will handle multiple clients using fork(). The basic routine is: server will wait for a connection, accept() it, and fork() a child process to handle it.

Server description

IN the socket prog 1st sockfd → listen on sockfd and new_fd → new conncn on new_fd is declared Then hints,*servinfo,*p are declared as struct addrinfo variable and pointers resp which will take care of addressing and lookup. Then their_addr is declared as a struct sockaddr_storage variable this stores the connecting clients address Then all the initialization is done by setting the struct addrinfo memory empty,setting ip family to accept both(ipv4 or ipv6),ip socket type to sock_stream,and flag to ai_passive so that it uses its own ip address. Then using getaddrinfo the whole ip,port info is added to the struct addrinfo hints and a pointer servinfo is attached to it. Now pointer p is assigned to servinfo and a socket descriptor sockfd is formed using socket() func Next using setsockopt all the unused ports can be reused. Then using bind() we can associate a socket with a port on the local machine. Now after using servinfo u can free it using freeaddrinfo. Now the server listens on the port for a new conn Now the server enters a infinite loop and services the requests from the clients and creates new descriptors new_fd for a new client

Server contd....................... The server now uses inet_ntop to convert the structure where the ip addr is located to number representation and stores the ip addr to a array s[ ]. Now for every new client it creates a descriptor and assingns it to a child process Now the listner sockfd is closed for this client using close(sockfd). Now the server uses send() method to send “Hello,World” message to the client After the whole process the client's connection is broken using close(new_fd).

server.c

Header files used in server.c

#include<stdio.h> - used for standard i/o #include<stdlib.h> - standard library defn. #include -defines miscellaneous symbolic constants and types, and declares miscellaneous funcn. #include <errno.h> - It defines macros to report error conditions through error codes #include<string.h> - string related funcn #include<sys/types.h> - defn of various datatypes. #include<sys/socket.h> - internet protocol family structures #include - internet address family structures #include - defn for N/W database operatn. #include <arpa/inet.h> - defn for internet operatn. #include <sys/wait.h> - declaratn for waiting #include <signal.h> - signal handling

cont... #define PORT "3490" → the port where users will connect . #define BACKLOG 10 → the no of pending connections The server queue may support.

struct sockaddr { unsigned short sa_family; // address family, AF_xxx char sa_data[14]; // 14 bytes of protocol address

}; struct sockaddr → holds socket address information for many types of sockets. sa_family → AF_INET(IP V4) or AF_INET6(IPV6)

sa_data → contains a destination address and port number for the socket.

To deal with struct sockaddr, programmers created a parallel structure: struct sockaddr_in (“in” for “Internet”) to be used with IPv4.a pointer to a struct sockaddr_in can be cast to a pointer to a struct sockaddr and vice-versa. struct sockaddr_in { short int sin_family; // Address family, AF_INET unsigned short int sin_port; // Port number struct in_addr sin_addr; // Internet address unsigned char sin_zero[8]; // Same size as struct sockaddr };

socket structures struct sockaddr: Holds socket address information for many types of sockets struct sockaddr { unsigned short sa_family; //address family AF_xxx unsigned short sa_data[14]; //14 bytes of protocol addr }

struct sockaddr_in: A parallel structure that makes it easy to reference elements of the socket address struct sockaddr_in { short int sin_family; // set to AF_INET unsigned short int sin_port; // Port number struct in_addr sin_addr; // Internet address unsigned char sin_zero[8]; //set to all zeros }

cont.. struct addrinfo struct addrinfo { int ai_flags; // AI_PASSIVE, AI_CANONNAME, etc. int ai_family; // AF_INET, AF_INET6, AF_UNSPEC int ai_socktype; // SOCK_STREAM, SOCK_DGRAM int ai_protocol; // use 0 for "any" size_t ai_addrlen; // size of ai_addr in bytes struct sockaddr *ai_addr; // struct sockaddr_in or _in6 char *ai_canonname; // full canonical hostname struct addrinfo *ai_next; // linked list, next node }; struct addrinfo is used to prep the socket address structures for subsequent use. It's also used in host name lookups, and service name lookups.

Initialization code int status; struct addrinfo hints; struct addrinfo *servinfo; will point to the results memset(&hints, 0, sizeof hints); make sure the struct is empty hints.ai_family = AF_UNSPEC; don't care IPv4 or Ipv6 hints.ai_socktype = SOCK_STREAM; TCP stream sockets hints.ai_flags = AI_PASSIVE; fill in my IP for me

getaddrinfo() int getaddrinfo( const char *node, // "www.example.com" or IP const char *service, // e.g. "http" or port number const struct addrinfo *hints, struct addrinfo **res); The node parameter is the host name to connect to, or an IP address. the parameter service, which can be a port number, like “80” hints parameter points to a struct addrinfo. res is a pointer that points to the results.

socket socket() -- Get the file descriptor syntax: int socket(int domain, int type, int protocol); domain should be set to AF_INET type can be SOCK_STREAM or SOCK_DGRAM set protocol to 0 to have socket choose the correct protocol based on type socket() returns a socket descriptor for use in later system calls or -1 on error

BIND() bind() - what port am I on? Used to associate a socket with a port on the local machine The port number is used by the kernel to match an incoming packet to a process int bind(int sockfd, struct sockaddr *my_addr, int addrlen) sockfd is the socket descriptor returned by socket() my_addr is pointer to struct sockaddr that contains information about your IP address and port addrlen is set to sizeof(struct sockaddr) returns -1 on error

connect() - Hello!

connect()

Connects to a remote host int connect(int sockfd, struct sockaddr *serv_addr, int addrlen) sockfd is the socket descriptor returned by socket() serv_addr is pointer to struct sockaddr that contains information on destination IP address and port addrlen is set to sizeof(struct sockaddr) returns -1 on error At times, you don't have to bind() when you are using connect()

listen() listen() - Call me please! Waits for incoming connections int listen(int sockfd, int backlog); sockfd is the socket file descriptor returned by socket() backlog is the number of connections allowed on the incoming queue listen() returns -1 on error Need to call bind() before you can listen()

accept() accept() - Thank you for calling ! accept() gets the pending connection on the port you are listen()ing on int accept(int sockfd, void *addr, int *addrlen); sockfd is the listening socket descriptor information about incoming connection is stored in addr which is a pointer to a local struct sockaddr_in addrlen is set to sizeof(struct sockaddr_in) accept returns a new socket file descriptor to use for this accepted connection and -1 on error

working // make a socket, bind it, and listen on it: sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); bind(sockfd, res->ai_addr, res->ai_addrlen); listen(sockfd, BACKLOG); // now accept an incoming connection: addr_size = sizeof their_addr; new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &addr_size); // ready to communicate on socket descriptor new_fd!

Send &recieve send() - Let's talk! The two functions are for communicating over stream sockets or connected datagram sockets. int send(int sockfd, const void *msg, int len, int flags); sockfd is the socket descriptor you want to send data to (returned by socket() or got with accept()) msg is a pointer to the data you want to send len is the length of that data in bytes set flags to 0 for now send() returns the number of bytes actually sent (may be less than the number you told it to send) or -1 on error

Cont.. send & rec

receive()-let's talk

syntax: int recv(int sockfd, void *buf, int len, int flags); sockfd is the socket descriptor to read from buf is the buffer to read the information into len is the maximum length of the buffer set flags to 0 for now recv() returns the number of bytes actually read into the buffer or -1 on error If recv() returns 0, the remote side has closed connection on you

close() close() - Bye Bye! int close(int sockfd); Closes connection corresponding to the socket descriptor and frees the socket descriptor Will prevent any more sends and recvs

setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) This code is added to reuse the port which was used for some other connectn previously but was still hanging in the kernel.

freeaddrinfo(servinfo); all done with this structure free the linked-list

struct sockaddr_storage their_addr; // connector's address information char s[INET6_ADDRSTRLEN];//space to hold the IPv4 string inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), s, sizeof s); This funcn converts string IP addresses to their binary representations.

Child processes if (!fork()) { // this is the child process close(sockfd); // child doesn't need the listener if (send(new_fd, "Hello, world!", 13, 0) == -1) perror("send");error has occurred close(new_fd);//close connection exit(0);//exit } close(new_fd); // parent doesn't need this } return 0; }

Basic client operation The client gets the server ip address from the command prompt Using getaddrinfo() the important structs are filled out with relevant info.the info is server ip address and port no to connect to. Now the socket is formed using the domain,type & protocol and stored in socket descriptor Now using connect the client connects to the server.connect funcn contains the sockfd(sock descriptor),a pointer to struct sockaddr() which contains the info on ip addr & port no.& the last is the sizeof (struct sockaddr)

cont..

In the beginning the sockfd ,MAXDATASIZE 100 macro is declared. Int buf[MAXDATASIZE] means that the buffer we can input max 100 bytes of data in the buffer. Then we declare a structure hint using struct addrinfo hints We declare 2 pointers to addinfo i.e *servinfo & *p Struct addrinfo is used to prepare the the address structures Then we initialize the hints structure to support both ipv4,ipv6 and to support a sock_stream kind of socket getaddrinfo helps in filling up the imp structs with ip addr,port etc.of the server.i.e these is stored in hints structure which is also pointed by serinfo pointer. Similarly socket() is used to return a socket descriptor Then we associate pointer p to servinfo and inturn to hints and search through all the results and then pass struct elements as parameters to socket and return a socket descriptor. Connect() is used to connect to a remote host

inet_ntop inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p>ai_addr), s, sizeof s); The struct addrinfo holds the server info inet_ntop func converts this struct info to numbers or dot representation The parameters passed to this are address type(ipv4 or ipv6),the adress,a pointer to a string to store the result,the max length of the string

cont..client if ((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) The recv func returns the no. of bytes actually read in the buffer,0 if conn is closed,-1 if error. { perror("recv");//if error occurs. exit(1);exit. } buf[numbytes] = '\0'; This statement stores '\0' that is end of string character in buf array when transfer of data is over. printf("client: received '%s'\n",buf); Display the data received in the buffer from the server. close(sockfd);//close the socket descriptor return 0; }

Related Documents

Unix Socket Quickref
December 2019 1
Unix
November 2019 40
Unix
May 2020 36
Unix
June 2020 24