2.2 socket programming - ntut.edu.twkwke/dc2006/socket programming in c.… · spc 1 network...

12
SPC 1 Network Applications Network Applications | | Socket Programming in C Socket Programming in C (Self (Self - - study and Practice) study and Practice) SPC 2 Versions of Socket APIs Versions of Socket APIs The Berkeley Socket API Berkeley Socket API - Developed in early1980s by UCB Allows programmers to write application programs easily w/o worrying about the underlying networking details Works well for many UNIX-like OS : OpenBSD, FreeBSD, Linux, HURD (free S/W foundation, GNU project.), Chorus (Sun Microsystems), etc. The Windows Socket Socket ( Winsock Winsock) API - Windows extension of Berkeley socket API by Microsoft A library of socket interface functions Need to import the wsock32.lib (in a 32-bit Windows environment). This library has to be linked in order to load the dynamic link library wsock32.dll at run time.) SPC 3 Winsock Layering Winsock Layering Application programmers write to the WinSock API and link their applications with the WINSOCK.LIB import library (or WSOCK32.LIB in the case of Win32). The application can then be installed on a computer that has a WinSock TCP/IP stack, from any number of vendors, and dynamically link to the WINSOCK.DLL (or WSOCK32.DLL) provided by the vendor. Win32 WinSock Application WINSOCK32.DLL Appl. Layer OS layer SPC 4 Socket System Calls Socket System Calls Creating a socket (an endpoint) #include <sys/socket.h> #include <sys/socket.h> #include <sys/types.h> int socket(int family, int type, int protocol); • commu. domaim, identified by a Address (AF) or a Protocol (PF) name • AF_UNIX, AF_INET, AF_OSI, PF_XXX ( = AF_XXX), etc. • AF_UNIX ~ file system pathname, commu. for local UNIX machine. AF_INET~ for Internet communication using TCP/IP • needed for socket related definitions • creates an unbounded socket & returns a file descriptor (nonneg. int.) • returns –1 in the case of a failure • needed for system defined identifiers

Upload: others

Post on 24-Jul-2020

7 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 2.2 Socket programming - ntut.edu.twkwke/DC2006/socket programming in C.… · SPC 1 Network Applications | Socket Programming in C (Self-study and Practice) SPC 2 Versions of Socket

SPC 1

Network ApplicationsNetwork Applications

||

Socket Programming in CSocket Programming in C

(Self(Self--study and Practice)study and Practice)SPC 2

Versions of Socket APIsVersions of Socket APIs• The Berkeley Socket APIBerkeley Socket API

- Developed in early1980s by UCB Allows programmers to write application programs easily w/o worrying about the underlying networking details

Works well for many UNIX-like OS : OpenBSD, FreeBSD, Linux, HURD (free S/W foundation, GNU project.), Chorus (Sun Microsystems), etc.

• The Windows SocketSocket (WinsockWinsock) API- Windows extension of Berkeley socket API by Microsoft

A library of socket interface functions Need to import the wsock32.lib (in a 32-bit Windows environment). This library has to be linked in order to load the dynamic link library wsock32.dll at run time.)

SPC 3

Winsock LayeringWinsock Layering

• Application programmers write to the WinSock API and link their applications with the WINSOCK.LIB import library (or WSOCK32.LIBin the case of Win32). The application can then be installed on a computer that has a WinSock TCP/IP stack, from any number of vendors, and dynamically link to the WINSOCK.DLL (or WSOCK32.DLL) provided by the vendor.

Win32 WinSock Application

WINSOCK32.DLLAppl. LayerOS layer

SPC 4

Socket System CallsSocket System CallsCreating a socket (an endpoint)

#include <sys/socket.h>#include <sys/types.h>int socket(int family, int type, int protocol);

#include <sys/socket.h>#include <sys/types.h>int socket(int family, int type, int protocol);

• commu. domaim, identified by a Address (AF) or a Protocol (PF) name• AF_UNIX, AF_INET, AF_OSI, PF_XXX ( = AF_XXX), etc. • AF_UNIX ~ file system pathname, commu. for local UNIX machine.• AF_INET~ for Internet communication using TCP/IP

• needed for socket related definitions

• creates an unbounded socket & returns a file descriptor (nonneg. int.)• returns –1 in the case of a failure

• needed for system defined identifiers

Page 2: 2.2 Socket programming - ntut.edu.twkwke/DC2006/socket programming in C.… · SPC 1 Network Applications | Socket Programming in C (Self-study and Practice) SPC 2 Versions of Socket

SPC 5

Creating a socket (cont’d)

#include <sys/socket.h>#include <sys/types.h>int socket(int family, int type, int protocol);

#include <sys/socket.h>#include <sys/types.h>int socket(int family, int type, int protocol);

• SOCK_STREAM (TCP, byte-stream, CO, reliable, sequenced, bidirectional),

SOCK_DGRAM (UDP, datagram, CL, unreliable), or SOCK_RAW (IP level)

• specifies the protocol used with socket• “0” ~ to use the default protocol for the

chosen domain and type (usually)(socket type)

default protocol of THE socket type

• Synopsis: if ((sd = socket(AF_INET, SOCK_DGRAM, 0) < 0){ printf(socket() failed.); exit(1); }

SPC 6

Assigning address to the socket created

#include <sys/socket.h>#include <sys/types.h>

int bind(int sd, struct sockaddr *addr, int addrlen);

#include <sys/socket.h>#include <sys/types.h>

int bind(int sd, struct sockaddr *addr, int addrlen);

• a local address and port # is associated w/ the socket• returns 0 on success & –1 on failure

• sd specifies (local) socket (file) descriptor returned by socket call

• addr is a pointer to the (local) address structure of this socket (containing local IP address and port #)

• addrlen is the length (in bytes) of the structure referenced by addr

SPC 7

Address structure sockaddr definition

struct sockaddr {unsigned short sa_family; /*address family, AF_XXX*/char sa_data[14]; /* protocol address */

}; /* 16-byte in total */

struct sockaddr {unsigned short sa_family; /*address family, AF_XXX*/char sa_data[14]; /* protocol address */

}; /* 16-byte in total */

• Needed for Internet address structure:#include <netinet/in.h>

• Generic address structure for many types of sockets:

• To deal with struct sockaddr, programmers created a parallel structure: (next page)

struct sockaddr_in ("in" for "Internet".)

• This structure makes it easy to reference elements of the socket addr.SPC 8

Socket address structure: for AF_INET

struct sockaddr_in {unsigned short sin_family; // AF_INET identifiers (host order)unsigned short sin_port; // 16-bit TCP/UDP port number,

// if 0, then kernel chosenstruct in_addr sin_addr; // 32-bit IP addresschar sin_zero[8]; // Unused, using memset() to all “0”

}; //16-byte, same as struct sockaddr

struct sockaddr_in {unsigned short sin_family; // AF_INET identifiers (hosthost order)unsigned short sin_port; // 16-bit TCP/UDP port number,

// if 0, then kernel chosenstruct in_addr sin_addr; // 32-bit IP addresschar sin_zero[8]; // Unused, using memset() to all “0”

}; //16-byte, same as struct sockaddr

#include <netinet/in.h>struct in_addr{ unsigned long s_addr; // store a 32-bit IP address };

#include <netinet/in.h>struct in_addr{ unsigned long s_addr; // store a 32-bit IP address }; • Must be in

NetworkNetwork Byte Order!

• A pointer to a struct sockaddr_in can be cast to a pointer to a structsockaddr and vice-versa. So even though socket() wants a structsockaddr*, you can still use a struct sockaddr_in tocast it.

Page 3: 2.2 Socket programming - ntut.edu.twkwke/DC2006/socket programming in C.… · SPC 1 Network Applications | Socket Programming in C (Self-study and Practice) SPC 2 Versions of Socket

SPC 9

Socket address structure: Synopsis

#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>struct sockaddr_in name;

...name.sin_family = AF_INET; // use the internet domainname.sin_port = htons(0); // kernel provides a portname.sin_addr.s_addr = htonl(INADDR_ANY);

// use current IP of hostif ( bind(local_socket, (struct sockaddr *)&name,

sizeof(name)) != 0 ){ printf(bind() failed.); exit(1); }

#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>struct sockaddr_in name;

...name.sin_family = AF_INET; // use the internet domainname.sin_port = htons(0); // kernel provides a portname.sin_addr.s_addr = htonl(INADDR_ANY);

// use current IP of hostif ( bind(local_socket, (struct sockaddr *)&name,

sizeof(name)) != 0 ){ printf(bind() failed.); exit(1); }

• Bind()Bind() is optional on the client side. We only care about where the remote port is. W/o calling bind(), the kernel will give a rndomlocal port # and the remote site will automatically get it in connection.

SPC 10

Data representation and byte ordering

• Big endian ~ store the high byte of an integer in the leftmost byte, while the low byte of an integer is stored in the rightmost byte (i.e., MSB first). E.g., Sun Sparc, M6800

• Little endian ~ vice versa (i.e., LSB first). E.g., i-386 PC

• Ex: The number 0x0564

0564Little endian

4650Big endian

13(high addr.)121110(low addr.)Memory address

• TCP/IP defines a machine independent standard: network byte order In a packet, the first transmitted data is the most significant bytenetwork byte order is big endian (Because big endian refers to storing the most significant byte in the lowest memory address).

leftmost rightmost

SPC 11

Byte order conversion

• unsigned long htonl(unsigned long n)~ host to network conversion of a 32-bit value (long);

• unsigned short htons(unsigned short n)~ host to network conversion of a 16-bit value (short);

• unsigned long ntohl(unsigned long n) ~ network to host conversion of a 32-bit value;

• unsigned short ntohs(unsigned short n) ~ network to host conversion of a 16-bit value.

• unsigned long htonl(unsigned long n)~ host to network conversion of a 32-bit value (long);

• unsigned short htons(unsigned short n)~ host to network conversion of a 16-bit value (short);

• unsigned long ntohl(unsigned long n) ~ network to host conversion of a 32-bit value;

• unsigned short ntohs(unsigned short n) ~ network to host conversion of a 16-bit value.

• Functions are used to convert from host to network ordering before transmission, and from network to host form after reception:

• h ~ host; n ~ network; s ~ short; l ~ long; a ~ ascii;• N.B.O. ~ network byte order

SPC 12

IP address Manipulation functions (1/3)• No need to figure them out by hand and stuff them in a long withthe « operator.

• Example: An IP address "10.12.110.57“ needed to be storedinto struct sockaddr_in ina. A programmer may do :

ina.sin_addr.s_addr = inet_addr("140.124.180.120");

inet_addr() takes a host address in dotted-decimal notation and returns corresponding 32-bit IP adddressIt returns the address in Network Byte Order already.

#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h>

unsigned long inet_addr(char *cp);

#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h>

unsigned long inet_addr(char *cp);

Page 4: 2.2 Socket programming - ntut.edu.twkwke/DC2006/socket programming in C.… · SPC 1 Network Applications | Socket Programming in C (Self-study and Practice) SPC 2 Versions of Socket

SPC 13

IP address Manipulation functions (2/3)

• Also: Converting 32-bit IP address in N.B.O. to dotted-decimal notation

• Q: There is no error checking. The inet_addr() returns -1 on error. Remember : a 32-bit (unsigned)-1 in Binary representation just happens to correspond to the IP address “255.255.255.255”!

That’s the broadcast address! So, be do error checking properly.

#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h>

char *inet_ntoa(struct in_addr in);

#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h>

char *inet_ntoa(struct in_addr in);SPC 14

IP address Manipulation functions (3/3)

#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h>int inet_aton(const char *cp, struct in_addr *inp);

#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h>int inet_aton(const char *cp, struct in_addr *inp);

• A cleaner function call : inet_aton() ~ ascii (a) to network (n)

• Example: Store IP addr. "10.12.110.57" struct sockaddr_in ina. struct sockaddr_in ina;ina.sin_family = AF_INET; // host byte orderina.sin_port = htons(MYPORT); // short, network byte orderinet_aton("10.12.110.57", &(ina.sin_addr));memset(&(ina.sin_zero), ’\0’, 8); // zero the rest of the struct

returns 32-bit IP addr in *inp on successand 0 on failure

SPC 15

Connecting a socket (connect)

#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>int connect(int local_s, struct sockaddr *remote_addr,

int rmtaddr_len); //return 0 on success

#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>int connect(int local_s, struct sockaddr *remote_addr,

int rmtaddr_len); //return 0 on success

• For CO-mode (TCP), it attempts to establish a connection to the remote destination specified by *remote_addr.

• For CL-mode (UDP), it store the server’s socket address that identifies where all datagrams are sent (no connection is made).

• local_s ~ is a local socket descriptor (e.g., client);• remote_addr ~ is a pointer to socket structure containing the

peer protocol address (e.g., server);• rmtaddr_len ~ is the length in bytes of the sockaddr address

structure.SPC 16

“connect” call synopsis:

#define PORT_NUM 1050 // Arbitrary port numberstruct sockaddr_in serv_addr; // Server Internet addressint rmt_s; // Remote socket descriptor/* Fill-in the server (remote) socket's address information and connect with the listening server */server_addr.sin_family = AF_INET; // Address family to useserver_addr.sin_port = htons(PORT_NUM); // Port num to useserver_addr.sin_addr.s_addr = inet_addr(inet_ntoa(IP address));if (connect(rmt_s,(struct sockaddr *)&serv_addr,

sizeof(serv_addr)) != 0){ printf(connect() failed.); exit(1); }

#define PORT_NUM 1050 // Arbitrary port numberstruct sockaddr_in serv_addr; // Server Internet addressint rmt_s; // Remote socket descriptor/* Fill-in the server (remote) socket's address information and connect with the listening server */server_addr.sin_family = AF_INET; // Address family to useserver_addr.sin_port = htons(PORT_NUM); // Port num to useserver_addr.sin_addr.s_addr = inet_addr(inet_ntoa(IP address));if (connect(rmt_s,(struct sockaddr *)&serv_addr,

sizeof(serv_addr)) != 0){ printf(connect() failed.); exit(1); }

• A connection-oriented server indicates its willingness to receive connection request by calling listen() call.

Page 5: 2.2 Socket programming - ntut.edu.twkwke/DC2006/socket programming in C.… · SPC 1 Network Applications | Socket Programming in C (Self-study and Practice) SPC 2 Versions of Socket

SPC 17

Listening to an incoming client connection request

#include <sys/socket.h>#include <sys/types.h>int listen(int sd, int q_length); // or the backlog

#include <sys/socket.h>#include <sys/types.h>int listen(int sd, int q_length); // or the backlog

• max. number of connections allowed on the server’s incoming queue (wait to be processed by the server).

• listen() returns an integer: 0 on success, and –1 on failure

• Synopsis: if (listen(sd, 5) < 0) { printf(listen() failed.); exit(1); }

SPC 18

Accepting a connection from client

#include <sys/socket.h>#include <sys/types.h>int accept(int server_s, struct sockaddr *client_addr,

int *clnaddr_len);

#include <sys/socket.h>#include <sys/types.h>int accept(int server_s, struct sockaddr *client_addr,

int *clnaddr_len);

• accept() returns a new socket descriptor on success or –1 on failure

• server_s ~ a bounded socket descriptor the server is listening on (i.e., the server’s socket)

• client_addr ~ filled with the client address• clntaddr_len ~ contains the length of the client address structure

SPC 19

Synopsis:

struct sockaddr_in client_addr;int server_s, client_s, clntaddr_len;...if ((client_s = accept(server_s, (struct sockaddr *)&client_addr, &clntaddr_len) < 0){ printf(accept() failed.); exit(1); }// at this stage a thread or a process can take over and handle// communication with the client

struct sockaddr_in client_addr;int server_s, client_s, clntaddr_len;...if ((client_s = accept(server_s, (struct sockaddr *)&client_addr, &clntaddr_len) < 0){ printf(accept() failed.); exit(1); }// at this stage a thread or a process can take over and handle// communication with the client

• The first queued incoming connection is accepted, and a new socket sd is created and returned. It is the socket thatthe server will use from now on to communicate with this client. (i.e., Server uses the returned (new) sd to perform data transfer.)

Once accept() being executed . . .

SPC 20

A few more to say about accept() on server . . .

• The first queued incoming connection is accepted, and a new socket sd is created and returned. It is the socket thatthe server will use from now on to communicate with this client. (i.e., Server uses the returned (new) sd to perform data transfer.)

• Concurrent server:- Multiple successful calls to connect() will result in multiple

new sockets returned.- Server can use the same server_s to accept further connectionrequest welcoming socket

- Successive calls to accept() on the same listening socket return different connected sockets. These connected sockets are multiplexed on the same port of the server by the running TCP stack functions.

Page 6: 2.2 Socket programming - ntut.edu.twkwke/DC2006/socket programming in C.… · SPC 1 Network Applications | Socket Programming in C (Self-study and Practice) SPC 2 Versions of Socket

SPC 21

Sending and Receiving data on a TCPTCP socket (CO)

#include <sys/socket.h>int send(int socket, const void *msg, unsigned int msg_length,

int flags);int recv(int socket, void *rcv_buff, unsigned int buff _length,

int flags);

#include <sys/socket.h>int send(int socket, const void *msg, unsigned int msg_length,

int flags);int recv(int socket, void *rcv_buff, unsigned int buff _length,

int flags);

• socket ~ the socket descrip. used to send and receive data• msg ~ the pointer to the buffer containing message to be sent/rec.• msg_length ~ the message length in bytes (pointer = address)• rcv_buff ~ a pointer to the buffer the rcved_msg should be stored• buff_length ~ The length of receiving buffer• flags ~ the type of message transmission/reception. Default = 0.

(e.g., MSG_OOB ~ requests out-of-band data.)

• Returns # of bytes of message sent/received or -1 on failure

SPC 22

Synopsis:

#include <sys/socket.h>. . . char *msg = “This is the text to be sent”;unsigned int msg_length, bytes_sent;. . .msg_length = strlen(msg);bytes_sent = send(server_s, msg, msg_length, 0);. . .

#include <sys/socket.h>. . . char *msg = “This is the text to be sent”;unsigned int msg_length, bytes_sent;. . .msg_length = strlen(msg);bytes_sent = send(server_s, msg, msg_length, 0);. . .

• send() returns the bytes # actually sent out, might < # asked to send• if byte_sent < msg_length to send the rest of the msg• if msg is small (say < 1kB or so), the send() will probably send it all in one go.

SPC 23

Sending data on a UDPUDP socket (CL mode)

#include <sys/socket.h>int sendto(int socket, const void *msg, unsigned int msg_length,

int flags, struct sockaddr *dest_addr, unsigned int addr_length);

#include <sys/socket.h>int sendto(int socket, const void *msg, unsigned int msg_length,

int flags, struct sockaddr *dest_addr, unsigned int addr_length);

• Callers of sendto() need to be informed of the to send *msg; • No guarantee on the delivery of the message

• Returns # of bytes of message sent or -1 on failure

• socket , msg, msg_length, flags are same as in the send()• dest_addr ~ points to a sockaddr structure containing the

destination address• addr_length ~ specifying the length of the sockaddr

structure pointed to by dest_addr

SPC 24

Receiving data on a UDPUDP socket (CL mode)

#include <sys/socket.h>int recvfrom(int socket, void *rcv_buff, unsigned int buff _length,

int flags, struct sockaddr *src_addr, unsigned int addr_length);

#include <sys/socket.h>int recvfrom(int socket, void *rcv_buff, unsigned int buff _length,

int flags, struct sockaddr *src_addr, unsigned int addr_length);

• Callers of recvfrom() need to distinguish between different sources sending datagram messages to the caller.

• Returns # of bytes of message received or -1 on failure

• socket, rcv_buff, buff_length, flags are same as in the recv()• src_addr ~ points to a sockaddr structure in which the sending

address to be stored (if it’s not a null pointer)• addr_length ~ specifying (regulating) the length of the sockaddr

structure pointed to by src_addr

Page 7: 2.2 Socket programming - ntut.edu.twkwke/DC2006/socket programming in C.… · SPC 1 Network Applications | Socket Programming in C (Self-study and Practice) SPC 2 Versions of Socket

SPC 25

Synopsis:. . . unsigned int server_s; // Server socket descriptorstruct sockaddr_in server_addr; // Server Internet addressint addr_len; // Internet address lengthchar out_buf[100]; // 100-byte output data bufferchar in_buf[100]; // 100-byte input data bufferserver_s = socket(AF_INET, SOCK_DGRAM, 0); // Create a socketserver_addr.sin_family = AF_INET; // Address family to useserver_addr.sin_port = htons(PORT_NUM); // Port num to useserver_addr.sin_addr.s_addr = inet_addr(IP_ADDR); // IP address to usestrcpy(out_buf, Message from client1 to server1); // Assign a message to out_buf// send message to server1. The + 1 includes the end-of-string delimitersendto(server_s, out_buf, (strlen(out_buf) + 1), 0, (struct sockaddr *)&server_addr,

sizeof(server_addr));// Wait to receive a messageaddr_len = sizeof(server_addr); //should be initialized to sizeof(sturct sockaddr).recvfrom(server_s, in_buf, sizeof(in_buf), 0, (struct sockaddr *)&server_addr,

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

. . . unsigned int server_s; // Server socket descriptorstruct sockaddr_in server_addr; // Server Internet addressint addr_len; // Internet address lengthchar out_buf[100]; // 100-byte output data bufferchar in_buf[100]; // 100-byte input data bufferserver_s = socket(AF_INET, SOCK_DGRAM, 0); // Create a socketserver_addr.sin_family = AF_INET; // Address family to useserver_addr.sin_port = htons(PORT_NUM); // Port num to useserver_addr.sin_addr.s_addr = inet_addr(IP_ADDR); // IP address to usestrcpy(out_buf, Message from client1 to server1); // Assign a message to out_buf// send message to server1. The + 1 includes the end-of-string delimitersendto(server_s, out_buf, (strlen(out_buf) + 1), 0, (struct sockaddr *)&server_addr,

sizeof(server_addr));// Wait to receive a messageaddr_len = sizeof(server_addr); //should be initialized to sizeof(sturct sockaddr).recvfrom(server_s, in_buf, sizeof(in_buf), 0, (struct sockaddr *)&server_addr,

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

SPC 26

Closing a socket

#include <sys/socket.h>int close(int socket);#include <sys/socket.h>int close(int socket);

• terminates a connection and return/free system resources to the OS• close() returns 0 on success or -1 on failure

// Create a socket/* - AF_INET is Address Family Internet and

SOCK_DGRAM is datagram */server_s = socket(AF_INET, SOCK_DGRAM, 0);. . .close(server_s);

// Create a socket/* - AF_INET is Address Family Internet and

SOCK_DGRAM is datagram */server_s = socket(AF_INET, SOCK_DGRAM, 0);. . .close(server_s);

Synopsis:

SPC 27

Running a socket program under Windows (WINSOCK)

#define WIN // WIN for Winsock #include <stdio.h> // Needed for printf()#include <stdlib.h> // Needed for exit()#include <string.h> // Needed for memcpy() and strcpy()#ifdef WIN

#include <windows.h> // Needed for all Winsock functions#endif. . .void main(int argc, char *argv[]) {#ifdef WIN

WORD wVersionRequested = MAKEWORD(1,1); // Stuff for WSA functionsWSADATA wsaData; // Stuff for WSA functions

#endif. . .#ifdef WIN

WSAStartup(wVersionRequested, &wsaData); // Initialize winsock#endif. . .

#ifdef WINWSACleanup(); // Clean up winsock

#endif }

#define WIN // WIN for Winsock #include <stdio.h> // Needed for printf()#include <stdlib.h> // Needed for exit()#include <string.h> // Needed for memcpy() and strcpy()#ifdef WIN

#include <windows.h> // Needed for all Winsock functions#endif. . .void main(int argc, char *argv[]) {#ifdef WIN

WORD wVersionRequested = MAKEWORD(1,1); // Stuff for WSA functionsWSADATA wsaData; // Stuff for WSA functions

#endif. . .#ifdef WIN

WSAStartup(wVersionRequested, &wsaData); // Initialize winsock#endif. . .

#ifdef WINWSACleanup(); // Clean up winsock

#endif }

• Need initialization, and different include and definition files

SPC 28

host name (information) defined in <netdb.h>

#define struct hostent {char *h_name; // (pointer to) official name of hostchar **h_aliases; // (pointer to) list of alias names for this host;

// terminated by a null (h_aliases[0] 1st one)int h_addrtype; // host address type, e.g. AF_INETint h_length; // length of address structure (always = 4)char **h_addr_list; // list of addresses in network byte order

// terminated by a null };#define h_addr h_addr_list[0] // the first entry holding Internet addr.

#define struct hostent {char *h_name; // (pointer to) official name of hostchar **h_aliases; // (pointer to) list of alias names for this host;

// terminated by a null (h_aliases[0] 1st one)int h_addrtype; // host address type, e.g. AF_INETint h_length; // length of address structure (always = 4)char **h_addr_list; // list of addresses in network byte order

// terminated by a null };#define h_addr h_addr_list[0] // the first entry holding Internet addr.

Network Utility FunctionsNetwork Utility Functions

• Defined in <winsock.h> for Winsock

Page 8: 2.2 Socket programming - ntut.edu.twkwke/DC2006/socket programming in C.… · SPC 1 Network Applications | Socket Programming in C (Self-study and Practice) SPC 2 Versions of Socket

SPC 29

Converting host name 32-bit IP address

#include <sys/socket.h>#include <sys/types.h>#include <sys/netdb.h>struct hostent *gethostbyname(char *hostname);

#include <sys/socket.h>#include <sys/types.h>#include <sys/netdb.h>struct hostent *gethostbyname(char *hostname);

• get host info from either /etc/hosts (host’s database) or a DNS server• returns a pointer to struct hostent on success or NULL(0) on error

Synopsis:#include <sys/socket.h>. . . struct hostent *h;. . .if (h = gethostbyname(char *hostname) = = NULL) { printf(gethostbyname() failed.); exit(1); }

#include <sys/socket.h>. . . struct hostent *h;. . .if (h = gethostbyname(char *hostname) = = NULL) { printf(gethostbyname() failed.); exit(1); }

*hostname can be "www.hinet.net";

SPC 30

#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <netdb.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>int main(int argc, char *argv[]){struct hostent *h; //buffer info of the hostif (argc != 2) { // error check the command linefprintf(stderr,"usage: getip address\n");exit(1);}if ((h = gethostbyname(argv[1])) = = NULL) { // get the host info

herror("gethostbyname"); // print errorexit(1);

}printf("Host name : %s\n", h->h_name);printf("IP Address : %s\n", inet_ntoa(*((struct in_addr *)h->h_addr)));return 0;}

#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <netdb.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>int main(int argc, char *argv[]){struct hostent *h; //buffer info of the hostif (argc != 2) { // error check the command linefprintf(stderr,"usage: getip address\n");exit(1);}if ((h = gethostbyname(argv[1])) = = NULL) { // get the host info

herror("gethostbyname"); // print errorexit(1);

}printf("Host name : %s\n", h->h_name);printf("IP Address : %s\n", inet_ntoa(*((struct in_addr *)h->h_addr)));return 0;}

Hostname Lookup ProgramHostname Lookup Program

SPC 31

Converting 32-bit IP address host name

#include <sys/socket.h>#include <sys/types.h>#include <sys/netdb.h>

struct hostent *gethostbyaddr(char *addr, int len, int type);

#include <sys/socket.h>#include <sys/types.h>#include <sys/netdb.h>

struct hostent *gethostbyaddr(char *addr, int len, int type);

• returns a pointer to struct hostent on success or NULL(0) on error

• a pointer to an array that contains a host (IP) address

• give the address length in bytes (4 for IP)

• address type (AF_INET for IP)

SPC 32

Send/Receive data using Write/Read Functions

#include <sys/socket.h>int write(int socket, &char wrt_buf, int buf_len);Int read(int socket, &char red_buf, int buf_len)

#include <sys/socket.h>int write(int socket, &char wrt_buf, int buf_len);Int read(int socket, &char red_buf, int buf_len)

• socket ~ the socket descrip. used to send and receive data• wrt_buf ~ the address of a buffer containing data• red_buff ~ a pointer to an array of characters to hold the data• buf_len ~ the number of bytes in the buffer array

• Returns # of bytes of message sent/received or -1 on failure• read() returns 0 if it detects an end-of-file on the socket

Page 9: 2.2 Socket programming - ntut.edu.twkwke/DC2006/socket programming in C.… · SPC 1 Network Applications | Socket Programming in C (Self-study and Practice) SPC 2 Versions of Socket

SPC 33

Example: TCP Echo Server/* A simple echo server using TCP */#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>

#define SERVER_TCP_PORT 3000#define BUFLEN 256

int main(int argc, char **argv){

int n, bytes_to_read;int sd, new_sd, client_len, port;struct sockaddr_in server, client;char *bp, buf[BUFLEN];

switch(argc) {case 1:

port = SERVER_TCP_PORT;break;

case 2:port = atoi(argv[1]);break;

default:fprintf(stderr, "Usage: %s [port]\n", argv[0]);exit(1);

}

/* Create a stream socket */if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {

fprintf(stderr, "Can't create a socket\n");exit(1);

}

/* Bind an address to the socket */bzero((char *)&server, sizeof(struct sockaddr_in));server.sin_family = AF_INET;server.sin_port = htons(port);server.sin_addr.s_addr = htonl(INADDR_ANY);if (bind(sd, (struct sockaddr *)&server, sizeof(server)) == -1) {

fprintf(stderr, "Can't bind name to socket\n");exit(1);

}

/* queue up to 5 connect requests */listen(sd, 5);

while (1) {client_len = sizeof(client);if ((new_sd = accept(sd, (struct sockaddr *)&client,&client_len)) == -1) {

fprintf(stderr, "Can't accept client\n");exit(1);

}

bp = buf;bytes_to_read = BUFLEN;while ((n = read(new_sd, bp, bytes_to_read)) > 0) {

bp += n;bytes_to_read -= n;

}printf("Rec'd: %s\n", buf);

write(new_sd, buf, BUFLEN);printf("Sent: %s\n", buf);close(new_sd);

}close(sd);return(0);

} SPC 34

Example: TCP Echo Client/* A simple TCP client */#include <stdio.h>#include <netdb.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>

#define SERVER_TCP_PORT 3000#define BUFLEN 256

int main(int argc, char **argv){

int n, bytes_to_read;int sd, port;struct hostent *hp;struct sockaddr_in server;char *host, *bp, rbuf[BUFLEN], sbuf[BUFLEN];

switch(argc) {case 2:

host = argv[1];port = SERVER_TCP_PORT;break;

case 3:host = argv[1];port = atoi(argv[2]);break;

default:fprintf(stderr, "Usage: %s host [port]\n", argv[0]);exit(1);

}

/* Create a stream socket */if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {

fprintf(stderr, "Can't create a socket\n");exit(1);

}

bzero((char *)&server, sizeof(struct sockaddr_in));server.sin_family = AF_INET;server.sin_port = htons(port);if ((hp = gethostbyname(host)) == NULL) {

fprintf(stderr, "Can't get server's address\n");exit(1);

}bcopy(hp->h_addr, (char *)&server.sin_addr, hp->h_length);

/* Connecting to the server */if (connect(sd, (struct sockaddr *)&server, sizeof(server)) == -1) {

fprintf(stderr, "Can't connect\n");exit(1);

}printf("Connected: server's address is %s\n", hp->h_name);

printf("Transmit:\n");gets(sbuf);

write(sd, sbuf, BUFLEN); // send it out

printf("Receive:\n");bp = rbuf;bytes_to_read = BUFLEN;while ((n = read(sd, bp, bytes_to_read)) > 0) {

bp += n;bytes_to_read -= n;

}printf("%s\n", rbuf);

close(sd);return(0);

}

SPC 35

Example: UDP Echo Server/* Echo server using UDP */#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>

#define SERVER_UDP_PORT 5000#define MAXLEN 4096

int main(int argc, char **argv){

int sd, client_len, port, n;char buf[MAXLEN];struct sockaddr_in server, client;

switch(argc) {case 1:

port = SERVER_UDP_PORT;break;

case 2:port = atoi(argv[1]);break;

default:fprintf(stderr, "Usage: %s [port]\n", argv[0]);exit(1);

}

/* Create a datagram socket */if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {

fprintf(stderr, "Can't create a socket\n");exit(1);

}

/* Bind an address to the socket */bzero((char *)&server, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(port);server.sin_addr.s_addr = htonl(INADDR_ANY);if (bind(sd, (struct sockaddr *)&server, sizeof(server)) == -1) {

fprintf(stderr, "Can't bind name to socket\n");exit(1);

}

while (1) {client_len = sizeof(client);if ((n = recvfrom(sd, buf, MAXLEN, 0, (struct sockaddr *)&client, &client_len)) < 0) {

fprintf(stderr, "Can't receive datagram\n");exit(1);

}

if (sendto(sd, buf, n, 0, (struct sockaddr *)&client, client_len) != n) {

fprintf(stderr, "Can't send datagram\n");exit(1);

}}close(sd);return(0);

}

SPC 36

Example: UDP Echo Client#include <stdio.h>#include <string.h>#include <sys/time.h>#include <netdb.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#define SERVER_UDP_PORT 5000#define MAXLEN 4096#define DEFLEN 64

long delay(struct timeval t1, struct timeval t2){

long d;d = (t2.tv_sec - t1.tv_sec) * 1000;d += ((t2.tv_usec - t1.tv_usec + 500) / 1000);return(d);

}int main(int argc, char **argv){

int data_size = DEFLEN, port = SERVER_UDP_PORT;int i, j, sd, server_len;char *pname, *host, rbuf[MAXLEN], sbuf[MAXLEN];struct hostent *hp;struct sockaddr_in server;struct timeval start, end;unsigned long address;

pname = argv[0];argc--;argv++;if (argc > 0 && (strcmp(*argv, "-s") == 0)) {

if (--argc > 0 && (data_size = atoi(*++argv))) {argc--;argv++;

}else {

fprintf(stderr,"Usage: %s [-s data_size] host [port]\n", pname);exit(1);

}}if (argc > 0) {

host = *argv;if (--argc > 0)

port = atoi(*++argv);}

else {fprintf(stderr,

"Usage: %s [-s data_size] host [port]\n", pname);exit(1);}

if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {fprintf(stderr, "Can't create a socket\n");exit(1);

}bzero((char *)&server, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(port);if ((hp = gethostbyname(host)) == NULL) {

fprintf(stderr, "Can't get server's IP address\n");exit(1);

}bcopy(hp->h_addr, (char *) &server.sin_addr, hp->h_length);

if (data_size > MAXLEN) {fprintf(stderr, "Data is too big\n");exit(1);

}for (i = 0; i < data_size; i++) {j = (i < 26) ? i : i % 26;sbuf[i] = 'a' + j;

}gettimeofday(&start, NULL); /* start delay measurement */

server_len = sizeof(server);if (sendto(sd, sbuf, data_size, 0, (struct sockaddr *)

&server, server_len) == -1) {fprintf(stderr, "sendto error\n");exit(1);

}if (recvfrom(sd, rbuf, MAXLEN, 0, (struct sockaddr *)&server, &server_len) < 0) {fprintf(stderr, "recvfrom error\n");exit(1);

}gettimeofday(&end, NULL); /* end delay measurement */if (strncmp(sbuf, rbuf, data_size) != 0)

printf("Data is corrupted\n");close(sd);return(0);

} /*end of main() */

Page 10: 2.2 Socket programming - ntut.edu.twkwke/DC2006/socket programming in C.… · SPC 1 Network Applications | Socket Programming in C (Self-study and Practice) SPC 2 Versions of Socket

SPC 37

Exercise: Executing a Remote .exe Program#include <stdio.h> // Needed for printf()#include <stdlib.h> // Needed for exit()#include <string.h> // Needed for memcpy() and strcpy()#include <windows.h> // Needed for Sleep() and Winsock stuff#include <fcntl.h> // Needed for file i/o constants#include <sys\stat.h> // Needed for file i/o constants#include <io.h> // Needed for open(), close(), and eof()#define PORT_NUM 1050 // Arbitrary port number for the server#define MAX_LISTEN 1 // Maximum number of listens to queue#define SIZE 256 // Size in bytes of transfer buffervoid main(int argc, char *argv[]){WORD wVersionRequested = MAKEWORD(1,1); // WSA functionsWSADATA wsaData; // Winsock API data structureunsigned int remote_s; // Remote socket descriptorstruct sockaddr_in remote_addr; // Remote Internet addressstruct sockaddr_in server_addr; // Server Internet addressunsigned char bin_buf[SIZE]; // Buffer for file tranferunsigned int fh; // File handleunsigned int length; // Length of buffers transferredstruct hostent *host; // Structure for gethostbyname()struct in_addr address; // Structure for Internet addresschar host_name[256]; // String for host nameint addr_len; // Internet address lengthunsigned int local_s; // Local socket descriptorstruct sockaddr_in local_addr; // Local Internet addressstruct in_addr remote_ip_addr; // Remote IP address// Check if number of command line arguments is validif (argc !=4){printf( *** ERROR - Must be 'local (host) (exefile) (outfile)' \n);printf( where host is the hostname *or* IP address \n);

Local site Local site programprogram

printf( of the host running remote.c, exefile is the \n);printf( name of the file to be remotely run, and \n);printf( outfile is the name of the local output file. \n);exit(1);}// Initialization of winsockWSAStartup(wVersionRequested, &wsaData);// Copy host name into host_namestrcpy(host_name, argv[1]);// Do a gethostbyname()host = gethostbyname(argv[1]);if (host == NULL){printf( *** ERROR - IP address for '%s' not be found \n, host_name);exit(1);}// Copy the four-byte client IP address into an IP address structurememcpy(&address, host->h_addr, 4);// Create a socket for remoteremote_s = socket(AF_INET, SOCK_STREAM, 0);// Fill-in the server (remote) socket's address information and connect// with the listening server.server_addr.sin_family = AF_INET; // Address family to useserver_addr.sin_port = htons(PORT_NUM); // Port num to useserver_addr.sin_addr.s_addr = inet_addr(inet_ntoa(address)); // IP addressconnect(remote_s, (struct sockaddr *)&server_addr, sizeof(server_addr));// Open and read *.exe fileif((fh = open(argv[2], O_RDONLY | O_BINARY, S_IREAD | S_IWRITE)) == -1){printf( ERROR - Unable to open file '%s'\n, argv[2]);exit(1);}

windows console

SPC 38

// Output message stating sending executable fileprintf(Sending '%s' to remote server on '%s' \n, argv[2], argv[1]);// Send *.exe file to remotewhile(!eof(fh)){length = read(fh, bin_buf, SIZE);send(remote_s, bin_buf, length, 0);}// Close the *.exe file that was sent to the server (remote)close(fh);// Close the socketclosesocket(remote_s);// Cleanup WinsockWSACleanup();// Output message stating remote is executingprintf( '%s' is executing on remote server \n, argv[2]);// Delay to allow everything to clean-upSleep(100);// Initialization of winsockWSAStartup(wVersionRequested, &wsaData);// Create a new socket to receive output file from remote serverlocal_s = socket(AF_INET, SOCK_STREAM, 0);// Fill-in the socket's address information and bind the socketlocal_addr.sin_family = AF_INET; // Address family to uselocal_addr.sin_port = htons(PORT_NUM); // Port num to uselocal_addr.sin_addr.s_addr = htonl(INADDR_ANY); // Listen on any IP addrbind(local_s, (struct sockaddr *)&local_addr, sizeof(local_addr));// Listen for connections (queueing up to MAX_LISTEN)listen(local_s, MAX_LISTEN);// Accept a connection, the accept will block and then return with// remote_addr filled in.addr_len = sizeof(remote_addr);remote_s = accept(local_s, (struct sockaddr*)&remote_addr, &addr_len);

• Local site program (cont’d)

// Copy the four-byte client IP address into an IP address structurememcpy(&remote_ip_addr, &remote_addr.sin_addr.s_addr, 4);// Create and open the output file for writingif ((fh=open(argv[3], O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,S_IREAD | S_IWRITE)) == -1){printf( *** ERROR - Unable to open '%s'\n, argv[3]);exit(1);}// Receive output file from serverlength = SIZE;while(length > 0){length = recv(remote_s, bin_buf, SIZE, 0);write(fh, bin_buf, length);}// Close output file that was received from the remoteclose(fh);// Close the socketsclosesocket(local_s);closesocket(remote_s);// Output final status messageprintf(Execution of '%s' and transfer of output to '%s' done! \n,argv[2], argv[3]);// Cleanup WinsockWSACleanup();}

SPC 39

Exercise: Executing a Remote .exe ProgramRemote site programRemote site program#include <stdio.h> // Needed for printf()

#include <stdlib.h> // Needed for exit()#include <string.h> // Needed for memcpy() and strcpy()#include <windows.h> // Needed for Sleep() and Winsock stuff#include <fcntl.h> // Needed for file i/o constants#include <sys\stat.h> // Needed for file i/o constants#include <io.h> // Needed for open(), close(), and eof()#define PORT_NUM 1050 // Arbitrary port number for the server#define MAX_LISTEN 1 // Maximum number of listens to queue#define IN_FILE run.exe // Name given to transferred *.exe file#define TEXT_FILE output // Name of output file for stdout#define SIZE 256 // Size in bytes of transfer buffervoid main(void){WORD wVersionRequested = MAKEWORD(1,1); // WSA functionsWSADATA wsaData; // WSA functionsunsigned int remote_s; // Remote socket descriptorstruct sockaddr_in remote_addr; // Remote Internet addressstruct sockaddr_in server_addr; // Server Internet addressunsigned int local_s; // Local socket descriptorstruct sockaddr_in local_addr; // Local Internet addressstruct in_addr local_ip_addr; // Local IP addressint addr_len; // Internet address lengthunsigned char bin_buf[SIZE]; // File transfer bufferunsigned int fh; // File handleunsigned int length; // Length of transf. buffers// Do foreverwhile(1){// Winsock initializationWSAStartup(wVersionRequested, &wsaData);

// Create a socket

remote_s = socket(AF_INET, SOCK_STREAM, 0);

// Fill-in my socket's address information and bind the socket

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

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

remote_addr.sin_addr.s_addr = htonl(INADDR_ANY); // Listen on any IP addr

bind(remote_s, (struct sockaddr *)&remote_addr, sizeof(remote_addr));

// Output waiting message

printf(Waiting for a connection... \n);

// Listen for connections (queueing up to MAX_LISTEN)

listen(remote_s, MAX_LISTEN);

// Accept a connection, accept() will block and return with local_addr

addr_len = sizeof(local_addr);

local_s = accept(remote_s, (struct sockaddr *)&local_addr, &addr_len);

// Copy the four-byte client IP address into an IP address structure

memcpy(&local_ip_addr, &local_addr.sin_addr.s_addr, 4);

// Output message acknowledging receipt, saving of *.exe

printf( Connection established, receiving remote executable file \n);

// Open IN_FILE for remote executable file

if((fh = open(IN_FILE, O_WRONLY | O_CREAT | O_TRUNC |

O_BINARY,

S_IREAD | S_IWRITE)) == -1)

{

printf( *** ERROR - unable to open executable file \n);

exit(1);

}SPC 40

// Receive executable file from local

length = 256;

while(length > 0)

{

length = recv(local_s, bin_buf, SIZE, 0);

write(fh, bin_buf, length);

}

// Close the received IN_FILE

close(fh);

// Close sockets

closesocket(remote_s);

closesocket(local_s);

// Cleanup Winsock

WSACleanup();

// Print message acknowledging execution of *.exe

printf( Executing remote executable (stdout to output file) \n);

// Execute remote executable file (in IN_FILE)

system(IN_FILE > TEXT_FILE);

// Winsock initialization to re-open socket to send output file to local

WSAStartup(wVersionRequested, &wsaData);

// Create a socket

// - AF_INET is Address Family Internet and SOCK_STREAM is streams

local_s = socket(AF_INET, SOCK_STREAM, 0);

// Fill in the server's socket address information and connect with

// the listening local

server_addr.sin_family = AF_INET;

server_addr.sin_port = htons(PORT_NUM);

server_addr.sin_addr.s_addr = inet_addr(inet_ntoa(local_ip_addr));

Remote site program (contRemote site program (cont’’d)d)connect(local_s, (struct sockaddr *)&server_addr, sizeof(server_addr));// Print message acknowledging transfer of output to clientprintf( Sending output file to local host \n);// Open output file to send to clientif((fh = open(TEXT_FILE, O_RDONLY | O_BINARY, S_IREAD |S_IWRITE)) == -1){printf( *** ERROR - unable to open output file \n);exit(1);}// Send output file to clientwhile(!eof(fh)){length = read(fh, bin_buf, SIZE);send(local_s, bin_buf, length, 0);}// Close output fileclose(fh);// Close socketsclosesocket(remote_s);closesocket(local_s);// Cleanup WinsockWSACleanup();// Delay to allow everything to clean-upSleep(100);}}

•• Assignment: Fix the problems if any and Assignment: Fix the problems if any and get it running on your Windows OS.get it running on your Windows OS.

Page 11: 2.2 Socket programming - ntut.edu.twkwke/DC2006/socket programming in C.… · SPC 1 Network Applications | Socket Programming in C (Self-study and Practice) SPC 2 Versions of Socket

SPC 41

IP Multicast Example - Linux• multicast server : simple multicast server that prints received messages.

source : mcastServer.cusage : ./mcastServer multicast_group

• multicast client : simple multicast client that sends data on multicast group.source : mcastClient.cusage : ./mcastClient multicast_group data1 ... dataN

/* mcastClient.c */

#include &lt;sys/types.h&gt;#include &lt;sys/socket.h&gt;#include &lt;netinet/in.h&gt;#include &lt;arpa/inet.h&gt;#include &lt;netdb.h&gt;#include &lt;stdio.h&gt;#include &lt;unistd.h&gt; /* close */#define SERVER_PORT 1500#define MAX_MSG 100

int main(int argc, char *argv[]) {int sd, rc, i;unsigned char ttl = 1;struct sockaddr_in cliAddr, servAddr;struct hostent *h;

• To Compile the program under Linux:gcc -Wall -o executable filename source.cEx: gcc -Wall -o mcastclient mcastclient.c

Warning all (possible) errors

SPC 42

IP Multicast Example (Client)if(argc&lt;3) {printf("usage %s &lt;mgroup&gt; &lt;data1&gt; &lt;data2&gt; ...

&lt;dataN&gt;\n",argv[0]);exit(1);

}

h = gethostbyname(argv[1]);if(h==NULL) {printf("%s : unknown host '%s'\n",argv[0],argv[2]);exit(1);

}

servAddr.sin_family = h-&gt;h_addrtype;memcpy((char *) &amp;servAddr.sin_addr.s_addr, h-&gt;h_addr_list[0],h-

&gt;h_length);servAddr.sin_port = htons(SERVER_PORT);

/* check if dest address is multicast */if(!IN_MULTICAST(ntohl(servAddr.sin_addr.s_addr))) {printf("%s : given address '%s' is not multicast \n",argv[0],

inet_ntoa(servAddr.sin_addr));exit(1);

}

/* create socket */sd = socket(AF_INET,SOCK_DGRAM,0);if (sd&lt;0) {printf("%s : cannot open socket\n",argv[0]);exit(1);

}

/* bind any port number */cliAddr.sin_family = AF_INET;cliAddr.sin_addr.s_addr = htonl(INADDR_ANY);

cliAddr.sin_port = htons(0);if(bind(sd,(struct sockaddr *) &amp;cliAddr,sizeof(cliAddr))&lt;0) {perror("bind");exit(1);

}

if(setsockopt(sd,IPPROTO_IP,IP_MULTICAST_TTL, &amp;ttl,sizeof(ttl))&lt;0) {printf("%s : cannot set ttl = %d \n",argv[0],ttl);exit(1);

}

printf("%s : sending data on multicast group '%s' (%s)\n",argv[0],h-&gt;h_name,inet_ntoa(*(struct in_addr *) h-&gt;h_addr_list[0]));

/* send data */for(i=2;i&lt;argc;i++) {rc = sendto(sd,argv[i],strlen(argv[i])+1,0,

(struct sockaddr *) &amp;servAddr, sizeof(servAddr));

if (rc&lt;0) {printf("%s : cannot send data %d\n",argv[0],i-1);close(sd);exit(1);

}

}/* end for */

/* close socket and exit */close(sd);exit(0);

}

SPC 43

IP Multicast Example (Server)/* mcastServer.c */

#include &lt;sys/types.h&gt;#include &lt;sys/socket.h&gt;#include &lt;netinet/in.h&gt;#include &lt;arpa/inet.h&gt;#include &lt;netdb.h&gt;#include &lt;stdio.h&gt;#include &lt;unistd.h&gt; /* close */#define SERVER_PORT 1500#define MAX_MSG 100

int main(int argc, char *argv[]) {

int sd, rc, n, cliLen;struct ip_mreq mreq;struct sockaddr_in cliAddr, servAddr;struct in_addr mcastAddr;struct hostent *h;char msg[MAX_MSG];

if(argc!=2) {printf("usage : %s &lt;mcast address&gt;\n",argv[0]);exit(0);

}

/* get mcast address to listen to */h=gethostbyname(argv[1]);if(h==NULL) {printf("%s : unknown group '%s'\n",argv[0],argv[1]);exit(1);

}

memcpy(&amp;mcastAddr, h-&gt;h_addr_list[0],h-&gt;h_length);

/* check given address is multicast */if(!IN_MULTICAST(ntohl(mcastAddr.s_addr))) {printf("%s : given address '%s' is not multicast\n",argv[0],

inet_ntoa(mcastAddr));exit(1);

}

/* create socket */sd = socket(AF_INET,SOCK_DGRAM,0);if(sd&lt;0) {printf("%s : cannot create socket\n",argv[0]);exit(1);

}

/* bind port */servAddr.sin_family=AF_INET;servAddr.sin_addr.s_addr=htonl(INADDR_ANY);servAddr.sin_port=htons(SERVER_PORT); if(bind(sd,(struct sockaddr *) &amp;servAddr, sizeof(servAddr))&lt;0) {printf("%s : cannot bind port %d \n",argv[0],SERVER_PORT);exit(1);

}

/* join multicast group */mreq.imr_multiaddr.s_addr=mcastAddr.s_addr;mreq.imr_interface.s_addr=htonl(INADDR_ANY);

rc = setsockopt(sd,IPPROTO_IP,IP_ADD_MEMBERSHIP,(void *) &amp;mreq, sizeof(mreq));

SPC 44

IP Multicast Example (Server)if(rc&lt;0) {

printf("%s : cannot join multicast group '%s'",argv[0],inet_ntoa(mcastAddr));

exit(1);}else {printf("%s : listening to mgroup %s:%d\n",

argv[0],inet_ntoa(mcastAddr), SERVER_PORT);

/* infinite server loop */while(1) {cliLen=sizeof(cliAddr);n = recvfrom(sd,msg,MAX_MSG,0,(struct sockaddr *)

&amp;cliAddr,&amp;cliLen);if(n&lt;n) {

printf("%s : cannot receive data\n",argv[0]);continue;

}

printf("%s : from %s:%d on %s : %s\n",argv[0],inet_ntoa(cliAddr.sin_addr),ntohs(cliAddr.sin_port),argv[1],msg);

}/* end of infinite server loop */

}

return 0;

}

Page 12: 2.2 Socket programming - ntut.edu.twkwke/DC2006/socket programming in C.… · SPC 1 Network Applications | Socket Programming in C (Self-study and Practice) SPC 2 Versions of Socket

SPC 45

ReferencesReferences• D. Comer and D. Stevens, Internetworking with TCP/IP, vol. 3:

Client-Server Programming and Applications (Linux/POSIX socket version), 3rd Ed., Prentice Hall, 2001.

• Brian Beej, Beej’s Guide to Network Programming Using Internet Sockets, 2001.

• Zornitza Genova, Sockets: A Programmer’s Introduction, 2003.• W. Stevens, UNIX Network Programming, vol.1, 2nd Ed., PH, 2002.• Q. Shute, Windows Socket Network Programming, Addison-Wesley, 1996.• http://linux.com.hk/PenguinWeb/manpages.jsp

SPC 46

Supplementary to Code Tracing Supplementary to Code Tracing -- II• Strings are groups or arrays of characters.

- Using string functions by : #include <string.h>• bcopy() ~ copy the first n-byte from src_addr to dest_addr

Ex: char src[30]=“string(src)”;char dest[30]=“string(dest)”;bcopy(src,dest,30); /* or memcpy(dest,src,30); strcpy(dest,src)*/

• strncmp() ~ compares the first n characters of two strings (ordering in ASCII).Ex: int value; /* ~ strcmp(s1,s2) */

char *s1,*s2; value = strncmp(s1,s2,n); /* returns s1?s2 “0/+diff/-diff” on “=/>/<” */

• gets() ~ reads a whole string from the input file stdin (the keyboard).Ex: char *string[length];

string = gets(string); /* puts(string); */• gettimeofday(strcut timeval *tv, strcut timezone *tz)

~ return current time and time-zone info in struct tv and tzEx: #include <sys/time.h>

#include <unistd.h>strcut timeval tv;

SPC 47

Supplementary to Code Tracing Supplementary to Code Tracing -- IIIIEx. (cont’d) strcut timezone tz;

gettimeofday(&tv, &tz);• perror(const char *s) ~ print “string s + error-clause”

Ex: #include <stdio.h>int socket_desc;socket_desc=socket(AF_INET,SOCK_STREAM,0); if (socket_desc==-1) perror("Create socket");

• unsigned int sleep(unsigned int secs) ~ force the current process to stop for secsEx: #include <unistd.h>

sleep(10);• system(const char *string) ~ executing a shell command

Ex: #include <stdlib.h>system(“ls –al /etc/user2”);

• void *memset(void *s, int c, size_t n) ~ filling the first n bytes of *s with c Ex: #include <string.h>

char s[20];memset(s,’A’, sizeof(s));s[20] = ‘\0’; /* end of the string */