Unix Socket Programming

  • Uploaded by: Ramaguru Radhakrishnan
  • 0
  • 0
  • 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 Programming as PDF for free.

More details

  • Words: 2,305
  • Pages: 57
UNIX SOCKET PROGRAMMING Outline Socket and Internet Sockets Network programming functions Socket System Calls TCP Sockets Programming UDP Sockets Programming

Sockets • Sockets provide mechanisms to communicate between computers across a network • There are different kind of sockets

• Berkeley sockets is the most popular Internet Socket – runs on Linux, FreeBSD, Windows

Network API • Operating system provides Application Programming Interface (API) for network application • API is defined by a set of function types, data structures, and constants • Application Programming Interface for networks is called socket

Internet Sockets • Support stream and datagram packets (e.g. TCP, UDP, IP) • Is Similar to UNIX file I/O API

• Based on C.

Types of Internet Sockets • Different types of sockets implement different communication types (stream vs. datagram) • Type of socket: stream socket – – – – –

connection-oriented two way communication reliable (error free), in order delivery can use the Transmission Control Protocol (TCP) e.g. telnet, http

• Type of socket: datagram socket – connectionless, does not maintain an open connection, each packet is independent – can use the User Datagram Protocol (UDP) – e.g. IP telephony

Data types int8_t uint8_t int16_t uint16_t int32_t uint32_t

signed 8bit int unsigned 8 bit int signed 16 bit int unsigned 16 bit int signed 32 bit int unsigned 32 bit int

u_char, u_short, u_int, u_long

More data types sa_family_t socklen_t in_addr_t in_port_t

address family length of struct IPv4 address IP port number

Naming and Addressing • Host name – identifies a single host – variable length string (e.g. www.berkeley.edu) – is mapped to one or more IP addresses • IP Address – written as dotted octets (e.g. 10.0.0.1) – 32 bits. Not a number! But often needs to be converted to a 32-bit to use. • Port number – identifies a process on a host – 16 bit number – Reserved ports ( 0 -1024 )

struct sockaddr_in (IPv4) struct sockaddr_in { uint8_t sin_len; sa_family_t sin_family; in_port_t sin_port; struct in_addr sin_addr; char sin_zero[8]; }; A special kind of sockaddr structure

struct in_addr struct in_addr { in_addr_t s_addr; }; in_addr_t

is uint32_t

Generic Socket Address • The sockets API is generic. • There must be a generic way to specify endpoint addresses. • TCP/IP requires an IP address and a port number for each endpoint address.

Generic socket addresses struct sockaddr uint8_t sa_family_t char };

{ sa_len; sa_family; sa_data[14];

• sa_family specifies the address type. • sa_data specifies the address value.

Generic Socket Address • We don’t need to deal with sockaddr structures since we will only deal with a real protocol family. • We can use sockaddr_in structures. BUT: Convert this socket address structure into generic one using type casting.

sockaddr

sockaddr_in

sa_len sa_family

sin_len AF_INET sin_port sin_addr

sa_data sin_zero

Network Programming Functions • • • •

Byte Ordering Byte Manipulation functions Addressing Socket system calls

Byte Ordering of Integers • Different CPU architectures have different byte ordering memory address A +1

Stored at little-endian computer Integer representation (2 byte) Stored at big-endian computer

high-order byte

D3

low-order byte

memory address A low-order byte

F2

high-order byte

Byte Order • Host Byte order Byte ordering used by a specific host • Network Byte order All values stored in a sockaddr_in must be in network byte order. – sin_port – sin_addr

a TCP/IP port number. an IP address.

Network Byte Order Functions ‘h’ : host byte order ‘s’ : short (16bit)

‘n’ : network byte order ‘l’ : long (32bit)

uint16_t htons(uint16_t); uint16_t ntohs(uint_16_t); uint32_t htonl(uint32_t); uint32_t ntohl(uint32_t);

Byte Manipulation Functions • Void bzero (void *dest, size_t nbytes) • Void bcopy (const void *src, void *dest, size_t nbytes) • Int bcmp (const void *ptr1, const void *ptr2, size_t nbytes)

IPv4 Address Conversion int inet_aton( char *, struct in_addr *); Convert ASCII dotted-decimal IP address to network byte order 32 bit value. Returns 1 on success, 0 on failure.

char *inet_ntoa(struct in_addr); Convert network byte ordered value to ASCII dotteddecimal (a string). a – ASCII dotted-decimal ipv4 address n –32 bit binary ipv4 address in network byte order

Creating a Socket int socket(int family,int type,int proto);

• family specifies the protocol family

(AF_INET for TCP/IP). • type specifies the type of service (SOCK_STREAM, SOCK_DGRAM). • protocol specifies the specific protocol (usually 0, which means the default).

socket() • The socket() system call returns a socket descriptor (small integer) or -1 on error. • socket() allocates resources needed for a communication endpoint - but it does not deal with endpoint addressing.

Bind() • The bind() system call is used to assign an address to an existing socket. • It tells the os to assign a local IP address and local port number to the socket. int bind( int sockfd, const struct sockaddr *myaddr, int addrlen);

• bind returns 0 if successful or -1 on error.

bind() Example int mysock,err; struct sockaddr_in myaddr; mysock = Socket(AF_INET,SOCK_STREAM,0); myaddr.sin_family = AF_INET; myaddr.sin_port = htons( portnum ); myaddr.sin_addr = htonl( ipaddress); err=bind(mysock, (struct sockaddr *) &myaddr, sizeof(myaddr));

Uses for bind() • There are a number of uses for bind(): – Server would like to bind to a well known address (port number). – Client can bind to a specific port. – Client can ask the O.S. to assign any available port number.

myaddr.port = htons(0);

Uses for bind() If the computer has multiple network interfaces? • There is no realistic way to know the right IP address for bind() • specify the IP address as: INADDR_ANY, this tells the OS to take care of things.

listen() int listen( int sockfd, int backlog); sockfd is the TCP socket (already bound to an address) Once we call listen(), the O.S. will queue incoming connections backlog is the number of incoming connections the kernel should queue for this socket. listen() returns -1 on error (otherwise 0).

accept() int accept( int sockfd, struct sockaddr* cliaddr, socklen_t *addrlen);

sockfd is the passive mode TCP socket. cliaddr is a pointer to allocated space. addrlen is a value-result argument – must be set to the size of cliaddr – on return, will be set to be the number of used bytes in cliaddr.

accept()

accept() returns a new socket descriptor (small positive integer) or -1 on error.

Connect() • TCP clients can call connect() which: – takes care of establishing an endpoint address for the client socket. • No need to call bind , the O.S. will take care of assigning the local endpoint address (TCP port number, IP address). – Attempts to establish a connection to the specified server. • 3-way handshake

connect() int connect( int sockfd, const struct sockaddr *server, socklen_t addrlen);

sockfd is an already created TCP socket. server contains the address of the server (IP Address and TCP port number) connect() returns 0 if OK, -1 on error

connect() After connection is established I/O can be done using the system calls.

Terminating a TCP connection

• Either end of the connection can call the close() system call.

Value-Result Parameters • Bind(),connect(), and sendto() pass a socket address from the process to the kernel. • Accept(), recvfrom() pass a socket address structure from kernel to the process. • Value – Tells the kernel the size of the structure. • Result – Tells the process how much information the kernel actually stored in the structure.

Concurrent servers • To handle multiple clients at the same time • The simplest way is to fork a child process to handle each client.

Simple TCP Client-Server Example response

Client

Server request

socket() connect() write()

read() close()

Connection establishment

socket() bind() listen() accept()

Data request

read()

Data response

write()

End-of-file notification

read() close()

Example: Client Programming • Create stream socket (socket() ) • Connect to server (connect() ) • While still connected: – send message to server (write() ) – receive (read() ) data from server and process it

• Close TCP connection and Socket (close())

Server Programming: Simple • • • •

Create stream socket (socket() ) Bind port to socket (bind() ) Listen for new client (listen() ) While – accept user connection and create a new socket (accept() ) – data arrives from client (read() ) – data has to be send to client (write() )

Creating & Binding TCP Socket int mysock; struct sockaddr_in myaddr; mysock=socket(PF_INET,SOCK_STREAM,0); myaddr.sin_family = AF_INET; myaddr.sin_port = htons( 80 ); myaddr.sin_addr = htonl( INADDR_ANY); bind(mysock,(struct sockaddr *) &myaddr, sizeof(myaddr));

Reading from a TCP socket int read( int fd, char *buf, int max);

• By default read() will block until data is available.

Writing to a TCP socket int write( int fd, char *buf, int num);

UDP Sockets Programming Server (Connectionless protocol)

socket ( )

bind ( )

Client socket ( )

recvfrom( )

bind ( ) blocks until data received from a client data (request)

sendo ( )

process request

recvfrom( )

sendto ( ) data reply

Socket system calls for connectionless protocol

Typical UDP client code • Create UDP socket. • Create sockaddr with address of server. • Call sendto(), sending request to the server. No call to bind() is necessary! • Possibly call recvfrom() (if we need a reply).

Typical UDP Server code • Create UDP socket and bind to well known address. • Call recvfrom() to get a request, noting the address of the client. • Process request and send reply back with sendto().

Creating & Binding UDP Socket int mysock; struct sockaddr_in myaddr; mysock = socket(PF_INET,SOCK_DGRAM,0); myaddr.sin_family = AF_INET; myaddr.sin_port = htons( 1234 ); myaddr.sin_addr = htonl( INADDR_ANY ); bind(mysock, &myaddr, sizeof(myaddr));

Sending UDP Datagrams ssize_t sendto( int sockfd, void *buff, size_t nbytes, int flags, const struct sockaddr* to, socklen_t addrlen);

sockfd is a UDP socket buff is the address of the data (nbytes long) to is the address of a sockaddr containing the destination address. Return value is the number of bytes sent, or -1 on error.

Receiving UDP Datagrams ssize_t recvfrom( int sockfd, void *buff, size_t nbytes, int flags, struct sockaddr* from, socklen_t *fromaddrlen);

sockfd is a UDP socket buff is the address of a buffer (nbytes long) from is the address of a sockaddr. Return value is the number of bytes received and put into buff, or -1 on error.

recvfrom() • If buff is not large enough, any extra data is lost ... • recvfrom doesn’t return until there is a datagram available. • The sockaddr at from is filled in with the address of the sender. • set fromaddrlen before calling.

Server Example #define MYPORT 3490 // the port users will be connecting to #define BACKLOG 10

// how many pending connections queue will hold

int main(void) { int sockfd, new_fd; // listen on sockfd, new connection on new_fd struct sockaddr_in my_addr; // my address information struct sockaddr_in their_addr; // connector's address information int sin_size; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } my_addr.sin_family = AF_INET; // host byte order my_addr.sin_port = htons(MYPORT); // short, network byte order my_addr.sin_addr.s_addr = INADDR_ANY; // auto. filled with local IP memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct 49

if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) { perror("bind"); exit(1); } if (listen(sockfd, BACKLOG) == -1) { perror("listen"); exit(1); } while(1) { // main accept() loop sin_size = sizeof(struct sockaddr_in); if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) { perror("accept"); continue; } printf("server: got connection from %s\n", inet_ntoa(their_addr.sin_addr)); if (send(new_fd, "Hello, world!\n", 14, 0) == -1) perror("send"); close(new_fd); } return 0; } 50

Client Example

#include #include <sys/socket.h>

#define PORT 3490 #define MAXDATASIZE 100

// the port client will be connecting to // max number of bytes we can get // at once

int main(int argc, char *argv[]) { int sockfd, numbytes; char buf[MAXDATASIZE]; struct hostent *he; struct sockaddr_in their_addr;

// server's address information

if (argc != 2) { fprintf(stderr,"usage: client hostname\n"); exit(1); } if ((he=gethostbyname(argv[1])) == NULL) { // get the host info perror("gethostbyname"); exit(1); } if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); }

51

their_addr.sin_family = AF_INET; // host byte order their_addr.sin_port = htons(PORT); // short, network byte order their_addr.sin_addr = *((struct in_addr *)he->h_addr); // already network byte order memset(&(their_addr.sin_zero), '\0', 8); // zero the rest of the struct if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1){ perror("connect"); exit(1); } if ((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) { perror("recv"); exit(1); } buf[numbytes] = '\0'; printf("Received: %s",buf); close(sockfd); return 0; }

52

Iterative (or sequential) Server • Handles one request at a time • Client waits for all previous requests to be processed • Unacceptable to user if long request blocks short request while (1) { accept a connection (or request) from a client service the client close the connection (if necessary) }

Concurrent Server • Can handle multiple requests at a time by creating new thread of control to handle each request • No waiting while (1) { accept a connection/request from client start a new thread to handle this client /* the thread must close the connection! */ }

Why Was There a Need to Introduce Concurrency in Client-Server •

Not effective conventional iterative method • Iterative servers are suitable for the most trivial services, (e.g., Time of Day, Local Time, Echo Servers, etc..) • They are NOT suitable for requests that require substantial amount of time to be completed, (e.g., FTP, TELNET, FILE SERVER, etc..) • Large amount of data could consume lot of time • This deprives communication for other client terminals • A concurrent server, on the other hand, is a server that can handle multiple requests.

- Concurrent Server can handle multiple requests at the same time - Server maintains a queue of connections. Client

Client

Internet Concurrent Server

- Iterative Server can handle only ONE request at a time. - No queues are maintained. - If the server is busy, client must retry again.

Client

Client

Client

Internet Iterative Server

Client

Thank you

Related Documents

Socket Programming
June 2020 9
Socket Programming
October 2019 24
Socket Programming
November 2019 22
Unix Socket Quickref
December 2019 1

More Documents from ""

Abstracts New Java
April 2020 28
Java Lab Questions
April 2020 18
Systemsoft(3)
May 2020 30
Record 55
April 2020 3
Record 2 Final
April 2020 8