2: application layer 1 socket programming unix network programming, socket programming tutorial:

28
2: Application Layer 1 Socket Programming UNIX Network Programming, http://beej.us/guide/bgnet/ Socket Programming Tutorial:

Upload: jeffry-shepherd

Post on 04-Jan-2016

256 views

Category:

Documents


0 download

TRANSCRIPT

2: Application Layer 1

Socket Programming

UNIX Network Programming,

http://beej.us/guide/bgnet/

Socket Programming Tutorial:

2: Application Layer 2

Socket basics

Socket: a door between application process and end-end-transport protocol (UDP or TCP)

Each host has 65,536 ports Some ports are reserved, for example:

HTTP: 80 FTP: 20, 21 Telnet: 23

sender explicitly attaches destination IP address and destination port number to each packet

server extracts IP address, port of sender from received packet

2: Application Layer 3

High Level View of a Socket: 5-tuple

Type of socket: TCP or UDP Local Port Local IP address Peer’s port (optional for UDP) Peer’s IP address (optional for UDP)

2: Application Layer 4

Struct sockaddr

Generic:struct sockaddr {

u_short sa_family; /* which address family */char sa_data[14]; /* the remaining 14 bytes */

};

For the Internet:struct sockaddr_in {

short sin_family; /* AF_INET */u_short sin_port; /* port 0-65535 */struct in_addr sin_addr; /* IP-address */char sin_zero[8]; /* unused */

};

struct in_addr {u_long s_addr; /* 32-bit netid/hostid */

}; /* network byte ordered */

2: Application Layer 5

Byte Ordering: Address and Port

Different Machines use different byte order for storing integers u_short sin_port is 16 bits in_addr sin_addr is 32 bits

Big Endian Notation Most Significant Byte (MSB) to Least Significant Byte (LSB) The IP address 164.107.112.44 will be stored as

Little Endian Notation LSB to MSB The IP address 164.107.112.44 will be stored as

Internet messages must follow Big Endian ordering

164 107 112 44

44 112 107 164

2: Application Layer 6

Byte Ordering Functionsfor handling byte order differences between Internet and some OSes

u_long htonl (u_long hostlong); u_short htons (u_short hostshort); u_long ntohl (u_long netlong); u_short ntohs (u_short netshort);

These functions implicitly assume that short is 16 bits and long is 32 bits

If host order is same as network order, the function simply returns the argument

networkhost

2: Application Layer 7

Socket System Calls for UDP

socket()socket()

bind()bind()

recvfrom()recvfrom()

process dataprocess data

sendto()sendto()

socket()socket()

bind()bind()

sendto()sendto()

recvfrom()recvfrom()

blocks until data received from client

data (request)

data (reply)

Client

Server

Time

application viewpoint

UDP provides unreliable data deliveryservice between client and server

2: Application Layer 8

socket():returns socket descriptor for use by later system calls, or -1 on error.

int socket (int family, int type, int protocol); family: set to AF_INET type

SOCK_STREAM : for TCP SOCK_DGRAM : for UDP SOCK_RAW : for IP (bypasses transport layer)

protocol to "0" to have socket() choose the correct protocol based on the type

Example sockfd = socket(AF_INET, SOCK_STREAM, 0);

2: Application Layer 9

bind():assigns a port to an unnamed socket

int bind (int sockfd, struct sockaddr *myaddr, int addrlen);

int sockfd; struct sockaddr_in my_addr;

sockfd = socket(AF_INET, SOCK_STREAM, 0); my_addr.sin_family = AF_INET; my_addr.sin_port = htons(5000); // short, network byte order my_addr.sin_addr.s_addr = inet_addr("10.12.110.57"); memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct

bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));

2: Application Layer 10

sendto(), recvfrom():send and receive through UDP sockets

int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);

Returns number of bytes sent

int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);

Returns number of bytes received

flag is normally set to 0

2: Application Layer 11

UDP server

#define PORT_NUM 1050 // Port number used

void main(void)

{

unsigned int server_s; // Server socket descriptor

struct sockaddr_in server_addr; // Server1 Internet address

struct sockaddr_in client_addr; // Client1 Internet address

int addr_len; // Internet address length

char out_buf[100]; // 100-byte buffer for output data

char in_buf[100]; // 100-byte buffer for input data

long int i; // Loop counter

server_s = socket(AF_INET, SOCK_DGRAM, 0);

// Fill-in my socket's address information

server_addr.sin_family = AF_INET; // Address family to use

server_addr.sin_port = htons(PORT_NUM); // Port number to use

server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // Listen on any IP address

bind(server_s, (struct sockaddr *)&server_addr, sizeof(server_addr));

addr_len = sizeof(client_addr);

recvfrom(server_s, in_buf, sizeof(in_buf), 0,

(struct sockaddr *)&client_addr, &addr_len);

printf("Message received is: '%s' \n", in_buf);

strcpy(out_buf, "Reply message from server1 to client1");

sendto(server_s, out_buf, (strlen(out_buf) + 1), 0,

(struct sockaddr *)&client_addr, sizeof(client_addr));

close(server_s);

}

2: Application Layer 12

UDP client

#define PORT_NUM 1050 // Port number used#define IP_ADDR "131.247.166.56" // IP address of server1void main(void){ unsigned int client_s; // Client socket descriptor struct sockaddr_in server_addr; // Server Internet address int addr_len; // Internet address length char out_buf[100]; // 100-byte buffer for output data char in_buf[100]; // 100-byte buffer for input data

client_s = socket(AF_INET, SOCK_DGRAM, 0);

// Fill-in server1 socket's address information server_addr.sin_family = AF_INET; // Address family to use server_addr.sin_port = htons(PORT_NUM); // Port num to use server_addr.sin_addr.s_addr = inet_addr(IP_ADDR); // IP address to use

// Assign a message to buffer out_buf strcpy(out_buf, "Test message from client1 to server1");

sendto(client_s, out_buf, (strlen(out_buf) + 1), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));

addr_len = sizeof(server_addr); recvfrom(client_s, in_buf, sizeof(in_buf), 0, (struct sockaddr *)&server_addr, &addr_len);

printf("Message received is: '%s' \n", in_buf);

close(client_s);}

2: Application Layer 13

Socket-programming using TCP

TCP service: reliable transfer of bytes from one process to another

process

TCP withbuffers,

variables

socket

controlled byapplicationdeveloper

controlled byoperating

system

host orserver

process

TCP withbuffers,

variables

socket

controlled byapplicationdeveloper

controlled byoperatingsystem

host orserver

internet

2: Application Layer 14

Socket System Calls for TCP

socket()socket()

bind()bind()

listen()listen()

accept()accept()

recv()recv()

send()send()

socket()socket()

connect()connect()

send()send()

recv()recv()

connection establishmentblocks until connection

from client

data (request)

data (reply)

Client

Server

Time

2: Application Layer 15

listen():sets limit on the maximum number of unprocessed incoming requests

int listen (int sockfd, int backlog); backlog is the number of connections allowed

on the incoming queue typical default is 20

2: Application Layer 16

accept():takes the first queued connection request and creates a new socket call blocks if no pending requests

int accept (int sockfd, void *peer, int *addrlen); sockfd is the socket descriptor peer will usually be a pointer to a local struct sockaddr_in to find out which

host is calling from which port

listen(sockfd, 10); sin_size = sizeof(struct sockaddr_in); new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);

2: Application Layer 17

accept():

for (; ;) {newsockfd = accept (sockfd, …); /* blocks */if (newsockfd < 0) {

fprintf(stderr,“accept error”);exit(0);

}if (fork() == 0) {

close(sockfd); /* child */do_something(newsockfd); /*process the request */exit(0);

}close (newsockfd);

}

for (; ;) {newsockfd = accept (sockfd, …); /* blocks */if (newsockfd < 0) {

fprintf(stderr,“accept error”);exit(0);

}do_something(newsockfd); /*process the request */close (newsockfd);

}

Iterative Server

Concurrent Server

2: Application Layer 18

connect():establishes connection with the serverdoes not return till connection is established or fails to connect

int connect (int sockfd, struct sockaddr *serv_addr, int addrlen); serv_addr is a struct sockaddr containing the destination port and IP address, addrlen is set to sizeof(struct sockaddr) Handshake messages are exchanged between the peers If called before bind(), OS automatically assigns a port If sockfd is a UDP socket, OS stores peer specific information from serv_addr

Subsequent calls for reading and writing do not require destination address or port number

sockfd = socket(AF_INET, SOCK_STREAM, 0);

dest_addr.sin_family = AF_INET; dest_addr.sin_port = htons(DEST_PORT); // short, network byte order dest_addr.sin_addr.s_addr = inet_addr(DEST_IP); memset(&(dest_addr.sin_zero), '\0', 8); // zero the rest of the struct

connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));

2: Application Layer 19

send(), recv():to send and recv data through TCP sockets or connect-ed UDP sockets

int send (int sockfd, const void *msg, int len, int flags); Returns the number of bytes sent

int recv (int sockfd, void *buf, int len, unsigned int flags); Returns the number of bytes received

flag is normally set to 0

2: Application Layer 20

select()to enable a process to wait for events on multiple sockets

int select (int maxfdpl, fd_set *readfds, fd_set *writefds, fd_set *execptfds, struct timeval * timeout);

Returns the number of ready descriptors or, -1 if none maxfdpl: 1+ largest file descriptor to check readfds: List of descriptors for checking if ready to read writefds: List of descriptors for checking if ready to write exceptfds: List of descriptors for checking if any exceptions timeout: timeout value to wait, NULL for infinite timeout

struct timeval {long tv_set; /* seconds */long tv_usec; /* microseconds */

}

2: Application Layer 21

select() (contd.)

Macros for setting/resetting/checking bits corresponding to sockets FD_ZERO (int fd, fd_set *fd_set); /* clear all bits in fdset */ FD_SET (int fd, fd_set *fd_set); /* turn on the bit for fd */ FD_CLR (int fd, fd_set *fd_set); /* turn off the bit for fd */ FD_ISSET (int fd, fd_set *fdset); /* test the bit for fd in fdset */

2: Application Layer 22

Select example

fd_set read_fd_set;

.... /* Initialize the set of active sockets. */ FD_ZERO (&read_fd_set); FD_SET (sock1, &read_fd_set); FD_SET (sock2, &read_fd_set);

while (1) { /* Block until input arrives on one or more active sockets. */ if (select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0) { perror ("select"); exit (EXIT_FAILURE); }

if (FD_ISSET (sock1, &read_fd_set)){

// sock1 is ready to be read }

if (FD_ISSET (sock2, &read_fd_set)){

// sock2 is ready to be read }

FD_ZERO (&read_fd_set); FD_SET (sock1, &read_fd_set); FD_SET (sock2, &read_fd_set); } }

2: Application Layer 23

close() :to close a socket

close (sockfd) frees socket descriptor frees the associated port

2: Application Layer 24

Address Conversion Routinesfor conversion between dotted-decimal format and in_addr structure

unsigned long inet_addr (char *ptr); Dotted decimal string to internet address

char * inet_ntoa (struct in_addr inaddr); Internet address to string format

2: Application Layer 25

Some other useful functions:

Socket Address getsockname: get IP and port of a socket getpeername: get IP and port of the other end of the socket

Host Name Gethostname

Host Information gethostbyname: get IP address from machine name gethostbyaddr: get machine name from IP address

Other send recv functions sendmsg/recvmsg

2: Application Layer 26

TCP server

#define PORT_NUM 1050 // Arbitrary port number for the servervoid main(void){ unsigned int server_s; // Server socket descriptor struct sockaddr_in server_addr; // Server Internet address unsigned int connect_s; // Connection socket descriptor struct sockaddr_in client_addr; // Client Internet address struct in_addr client_ip_addr; // Client IP address int addr_len; // Internet address length char out_buf[100]; // 100-byte output buffer for data char in_buf[100]; // 100-byte input buffer for data

server_s = socket(AF_INET, SOCK_STREAM, 0);

// Fill-in my socket's address information and bind the socket server_addr.sin_family = AF_INET; // Address family to use server_addr.sin_port = htons(PORT_NUM); // Port number to use server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // Listen on any IP address bind(server_s, (struct sockaddr *)&server_addr, sizeof(server_addr));

listen(server_s, 1);

// Accept a connection. The accept() will block and then return with // connect_s assigned and client_addr filled-in. addr_len = sizeof(client_addr); connect_s = accept(server_s, (struct sockaddr *)&client_addr, &addr_len);

2: Application Layer 27

TCP server(contd.)

memcpy(&client_ip_addr, &client_addr.sin_addr.s_addr, 4);

printf("Accept completed!!! IP address of client = %s port = %d \n", inet_ntoa(client_ip_addr), ntohs(client_addr.sin_port));

strcpy(out_buf, "Test message from server to client"); send(connect_s, out_buf, (strlen(out_buf) + 1), 0);

recv(connect_s, in_buf, sizeof(in_buf), 0); printf("Received from client... data = '%s' \n", in_buf);

close(server_s); close(connect_s);}

2: Application Layer 28

TCP client

#define PORT_NUM 1050 // Port number used at the server#define IP_ADDR "131.247.166.56" // IP address of server

void main(void){ unsigned int client_s; // Server socket descriptor struct sockaddr_in server_addr; // Server Internet address char out_buf[100]; // 100-byte output buffer for data char in_buf[100]; // 100-byte input buffer for data

client_s = socket(AF_INET, SOCK_STREAM, 0);

// Fill-in the client socket's address information and do a connect with // the listening server. server_addr.sin_family = AF_INET; // Address family to use server_addr.sin_port = htons(PORT_NUM); // Port num to use server_addr.sin_addr.s_addr = inet_addr(IP_ADDR); // IP address to use connect(client_s, (struct sockaddr *)&server_addr, sizeof(server_addr));

recv(client_s, in_buf, sizeof(in_buf), 0); printf("Received from server... data = '%s' \n", in_buf);

strcpy(out_buf, "Test message from client to server"); send(client_s, out_buf, (strlen(out_buf) + 1), 0);

close(client_s);}