2: Application Layer 1 Socket Programming UNIX Network Programming, Socket Programming Tutorial:
-
Upload
nora-webster -
Category
Documents
-
view
251 -
download
0
description
Transcript of 2: Application Layer 1 Socket Programming UNIX Network Programming, Socket Programming Tutorial:
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()
bind()
recvfrom()
process data
sendto()
socket()
bind()
sendto()
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()
bind()
listen()
accept()
recv()
send()
socket()
connect()
send()
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
int inet_aton(const char *cp, struct in_addr *inp) 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);}