1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C -...

71
1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer Communications, 8th edition By William Stallings Reference: Internetworking With TCP/IP, Volume III: Client-Server Programming And Applications, Windows Socket Version By Douglas E. Comer and David L. Stevens.
  • date post

    21-Dec-2015
  • Category

    Documents

  • view

    214
  • download

    0

Transcript of 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C -...

Page 1: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

1

Data Communications and Networking

Socket Programming Part I:Preliminary

Reading:Appendix C - Sockets: A Programmer’s IntroductionData and Computer Communications, 8th editionBy William Stallings

Reference:Internetworking With TCP/IP, Volume III: Client-Server Programming And Applications, Windows Socket VersionBy Douglas E. Comer and David L. Stevens.

Page 2: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

2

Learning Outcomes• Knowledge

—Explain the principles of network programming

—Explain the client-server model

—Get familiar with WinSock APIs

• Skills—Design and develop the client side of client-server network

applications using socket programming

Page 3: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

3

Outline• Client Server Model• Concept of Socket • Address Structures

—Byte order

• WinSock API• Client Software Design

—TCP

—UDP

Page 4: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

4

Client Server Model• TCP/IP allows two application programs to pass data

back and forth—The applications can execute on the same machine or on

different machines

• How to organize the application programs?—Client-server paradigm is the most popular model

• The communication applications are divided into two categories: client and server

• Client-server paradigm uses the direction of initiation to categorize whether a program is a client or server.

Page 5: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

5

Client Server Model (Cont.)• An application that initiates the communication is called a

client—E.g., Web browser, FTP client, Telnet client, Email client

—The client contacts a server, sends a request, and awaits a response

• An application that waits for incoming communication requests from clients is called a server—E.g., Web server, FTP server, Telnet server, SMTP server

—The server receives a client’s request, performs the necessary computation, and returns the result to the client

—Remark: A server is usually designed to provide service to multiple clients

• How ???

Page 6: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

6

Client Server Model (Cont.)

Web Server

Request

Request

Req

uestResponse

Response

Response

Client Programs:Web browsers

Remark:

Because the Web servers and Web browsers are designed based on HTTP, different Web browsers can communicate with all kinds of Web servers.

Page 7: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

7

Time Service: An Example• Time service: based on Time Protocol (RFC868)

—http://www.faqs.org/rfcs/rfc868.html

—The Time service sends back to the originating source the time in seconds since midnight on January first 1900

—Can use TCP or UDP

• Time protocol (when using UDP):— Server: Listen on port 37.

— Client: Send an empty datagram to port 37.

— Server: Receive the empty datagram.

— Server: Send a datagram containing the time as a 32 bit binary number.

— Client: Receive the time datagram.

Page 8: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

8

Time Service: Server Program#include <stdio.h> #include <stdlib.h>#include <time.h> #include <string.h>#include <stdarg.h> #include <winsock2.h>

#define SA struct sockaddr#define MAXLINE 4096#define S_PORT 37#define WINEPOCH 2208988800

int main(int argc, char **argv){ WSADATA wsadata; struct sockaddr_in servaddr, cliaddr; char buff[MAXLINE]; time_t ticks; /* current time */ int n, len; SOCKET s;

if (WSAStartup(MAKEWORD(2,2), &wsadata) != 0)errexit("WSAStartup failed\n");

/* Fill up the servaddr */ memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = INADDR_ANY; servaddr.sin_port = htons(S_PORT);

s = socket(AF_INET, SOCK_DGRAM, 0);

if (s == INVALID_SOCKET) errexit("cannot create socket: error number %d\n", WSAGetLastError());

/* Bind the servaddr to socket s */ if (bind(s, (SA *) &servaddr, sizeof(servaddr)) == SOCKET_ERROR) errexit("can't bind to port %d: error number %d\n", S_PORT, WSAGetLastError());

for ( ; ; ) { len = sizeof(SA); if (n = recvfrom(s, buff, sizeof(buff), 0, (SA *)&cliaddr, &len) == SOCKET_ERROR) errexit("recvfrom error: error number %d\n", WSAGetLastError());

time(&ticks); /* returns the number of seconds elapsed since midnight of January 1, 1970 */ ticks = htonl((u_long)(ticks + WINEPOCH)); sendto(s, (char *)&ticks, sizeof(ticks), 0, (SA *)&cliaddr, sizeof(cliaddr)); } /* end of for loop */}

Page 9: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

9

Time Service: Client Program#include <stdio.h> #include <stdlib.h>#include <time.h> #include <string.h>#include <stdarg.h> #include <winsock2.h>

#define SA struct sockaddr#define MAXLINE 4096#define S_PORT 37#define WINEPOCH 2208988800

int main(int argc, char **argv){ WSADATA wsadata; SOCKET s; int n, len; time_t now; struct sockaddr_in servaddr;

/* Must initialize the socket DLL first */ if (WSAStartup(MAKEWORD(2,2), &wsadata) != 0) errexit("WSAStartup failed\n");

if (argc != 2) errexit("usage: daytimeudpcli <IPaddress>");

/* Create a socket, and check the return value */ if ( (s = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET )

errexit("socket error: error number %d\n", WSAGetLastError());

memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(S_PORT); if ( (servaddr.sin_addr.s_addr = inet_addr(argv[1])) == INADDR_NONE) errexit("inet_addr error: error number %d\n", WSAGetLastError());

sendto(s, NULL, 0, 0, (SA *)&servaddr, sizeof(servaddr));

len = sizeof(SA); n = recvfrom(s, (char *)&now, sizeof(now), 0, (SA *)&servaddr, &len); if (n == SOCKET_ERROR) errexit("recvfrom failed: error number %d\n", WSAGetLastError());

now = ntohl((u_long)now); now -= WINEPOCH; printf("%s", ctime(&now));

WSACleanup();

return 0;}

Page 10: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

10

How to Write Network Applications?• TCP/IP is implemented inside the OS • OS exports the TCP/IP functionalities through

SOCKET APIs —API: Application Program Interface—A set of functions

• Programmers develop network applications by using SOCKET APIs

• To learn SOCKET programming—Learn some data structures—Learn the socket APIs—Learn multi-threading

Page 11: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

11

Socket Abstraction

• “Socket” is an interface between applications and the network services provided by OS

• An application sends and receives data through a socket

ApplicationApplication

SOCKETSOCKET API API

TCP/IPv4TCP/IPv4 TCP/IPv6TCP/IPv6 UNIXUNIX

Page 12: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

12

Socket Abstraction (Cont.)

Process A Process B

socket socket

data datadata

Page 13: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

13

Socket Abstraction (Cont.)

Browser A Browser B

socket socket

Web Server

Browser C

socket

Page 14: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

14

History of Sockets• In early 1980s, the Advanced Research Projects Agency (ARPA) funded a

group at UC Berkeley to transport TCP/IP software to the UNIX operating system.

• As part of the project, the designers created an interface that applications use for network communication.

• The interface used an abstraction known as a socket, and the API became known as socket API.

• Many computer vendors adopted the Berkeley UNIX operating system, and the socket interface became very popular.

• Subsequently, Microsoft chose the socket interface as the primary network API for its operating systems, called WinSock.— Old version: Windows Sockets 1.1— Today’s version: Windows Sockets 2

• http://www.sockets.com/winsock2.htm• The important header file: winsock2.h

• The socket interface has become a de facto standard throughout the computer industry.

Page 15: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

15

Specifying a Protocol Interface• The designers at Berkeley wanted to accommodate

multiple sets of communication protocols.— TCP/IP was not the only choice at that time!

• They allowed for multiple families of protocols, with TCP/IP represented as a single family. E.g.,— PF_INET or AF_INET (IPv4)

• Our focus

— PF_INET6 or AF_INET6 (IPv6)— PF_UNIX or AF_UNIX (Unix domain protocols)— PF_IPX or AF_IPX (IPX protocols)

Page 16: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

16

Socket Descriptors• To perform file I/O, we use a file descriptor.• Similarly, to perform network I/O, we use a socket

descriptor:— Each active socket is identified by its socket descriptor. — The data type of a socket descriptor is SOCKET.— Hack into the header file winsock2.h:

• typedef u_int SOCKET; /* u_int is defined as unsigned int */

— In UNIX systems, socket is just a special file, and socket descriptors are kept in the file descriptor table.

— The Windows operating system keeps a separate table of socket descriptors (named socket descriptor table, or SDT) for each process.

Page 17: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

17

How to Create a Socket?• The socket API contains a function socket() that can

be called to create a socket. E.g.:

#include <winsock2.h>…SOCKET s; …s = socket(AF_INET, SOCK_DGRAM, 0) ;

The socket is not usable yet. We need

to specify more information before

using it for data transmission.

Page 18: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

18

Types of Sockets• Under protocol family AF_INET

—Stream socket• Uses TCP for connection-oriented reliable communication

• Identified by SOCK_STREAM

• s = socket(AF_INET, SOCK_STREAM, 0) ;

—Datagram socket• Uses UDP for connectionless communication

• Identified by SOCK_DGRAM

• s = socket(AF_INET, SOCK_DGRAM, 0) ;

—RAW socket• Uses IP directly

• Identified by SOCK_RAW

• Advanced topic. Not covered by COMP2330.

Page 19: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

19

System Data Structures for Sockets• When an application process calls socket(), the operating system allocates

a new data structure to hold the information needed for communication, and fills in a new entry in the process’s socket descriptor table (SDT) with a pointer to the data structure.— A process may use multiple sockets at the same time. The socket descriptor

table is used to manage the sockets for this process.

— Different processes use different SDTs.

• The internal data structure for a socket contains many fields, but the system leaves most of them unfilled. The application must make additional procedure calls to fill in the socket data structure before the socket can be used.

• The socket is used for data communication between two processes (which may locate at different machines). So the socket data structure should at least contain the address information, e.g., IP addresses, port numbers, etc.

Page 20: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

20

System Data Structures for Sockets (Cont.)

Conceptual operating system (Windows) data structures after five calls to socket() by a process. The system keeps a separate socket descriptor table for each process; threads in the process share the table.

Fig 5.2 from Comer.

Page 21: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

21

C Review: Structure • C structures are collections of related variables under

one name.

struct employee {

char firstname[20];

char lastname[20];

int age;

float salary;

};

typedef struct employee Employee;

Employee em;

Employee *pEm; /* pointer to structure */

em.salary = 23456; /* dot operator */

pEm = &em; /* assign address of em to pEm */

pEm->salary += 1000; /* struct pointer operator */

Page 22: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

22

memset() and memcpy()memset(): set buffer to a specified character

void *memset(void *dest, int c, size_t count);—dest : Pointer to destination.

—c : Character to set.

—count : Number of characters

memcpy(): copy characters between buffers

void *memcpy(void *dest, const void *src, size_t count);—dest : New buffer.

— src : Buffer to copy from.

—count : Number of bytes to copy.

Page 23: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

23

Addressing Issue• How to identify a communication?

— Source IP Address, Source Port Number, Destination IP Address, Destination Port Number

—TCP or UDP

• IPv4 address: 32-bit• Port number: 16-bit

—http://www.iana.org/assignments/port-numbers

• Better to have a data structure that contains the addressing information—To simplify the socket APIs—Number of function parameters can be decreased

Page 24: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

24

Specifying an Endpoint Address• When a socket is created, it doesn’t contain address

information of either local machine or the remote machine.• Before an application uses a socket for sending/receiving data,

it must specify one or both of these addresses for the socket.— This can simplify the APIs.

• TCP/IP define a communication endpoint to consist of an IP address and a protocol port number.— when you create the socket, you already specified whether this socket

is using TCP or UDP.

• Several data structures are involved to represent the endpoint address— A general structure: struct sockaddr — A specific structure for IPv4: struct sockaddr_in

Page 25: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

25

Generic Address Structure• The socket system defines a generic endpoint address:

— (address family, endpoint address in that family)— The purpose is to provide a common interface for different kinds of

protocol families

struct sockaddr { u_short sa_family; /* address family */ char sa_data[14]; /* up to 14 bytes of direct address */};

• Unfortunately, not all address families define endpoints that fit into the sockaddr structure!

• To keep program portable and maintainable, TCP/IP code should not use the sockaddr structure in declarations.

• Instead, another structure sockaddr_in should be used to represent a socket address in AF_INET family.

Page 26: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

26

struct sockaddr_in { short sin_family; /* type of address, always AF_INET */ u_short sin_port; /* protocol port number */ struct in_addr sin_addr; /* IP address */ char sin_zero[8]; /* unused */};

TCP/IP Endpoint Address• TCP/IP (IPv4) endpoint address is defined as:

(AF_INET, 2-byte port number, 4-byte IP address, 8-byte zero).

The IP address is stored in structure sin_addr with type struct in_addr:

The 32-bit IP address can be explained as 4 unsigned bytes, or 2 unsigned short, or an unsigned long. By using a union, you can manipulate the IP address conveniently.

struct in_addr { union { struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b; struct { u_short s_w1,s_w2; } S_un_w; u_long S_addr; } S_un;#define s_addr S_un.S_addr …};

Page 27: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

27

sockaddr vs. sockaddr_in

struct sockaddr struct sockaddr_in

sa_family sin_family

sa_data

sin_port

sin_addr

sin_zero

2 bytes

2 bytes

4 bytes

8 bytes

2 bytes

14 bytes

A pointer to a struct sockaddr_in can be cast to a pointer to a struct sockaddr and vice-versa.

Page 28: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

28

An Example• To specify an endpoint address 158.182.9.1:5678

#include <winsock2.h>

struct sockaddr_in addr;

addr.sin_family = AF_INET;

addr.sin_port = htons(5678);

addr.sin_addr.s_addr = htonl(2662729985);

There are several ways to specify an IP address:

• Use a string – Good!

• “158.182.9.1”• Use an integer – Bad!

• 2662729985

• Use DNS service – Good!

Remark: 2662729985 = 10011110101101100000100100000001158 182 9 1

Page 29: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

29

Byte Ordering• Byte Ordering:

• Memory is organized in bytes.

• E.g, a 16-bit integer takes 2 consecutive bytes; a 32-bit integer takes 4 consecutive bytes.

• Different machines use different host bye orderings:

• little-endian: least significant byte located at lower memory

• E.g., Intel 80x86

• big-endian: least significant byte located at higher memory

• E.g., Motorola 68000

• These machines may communicate with one another over the network, and they may have different understandings on the same data.

• Not a problem for data type char

Page 30: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

30

Chaos of Byte Order

00001010000101110000111000000110

A

A+1

A+2

A+3

Memory

Big-Endian Little-Endian

00001010 00010111 00001110 00000110 00000110 00001110 00010111 00001010

A+3A+2A+1A AA+1A+2A+3

169283078 68032266

MemoryAddress

Big-Endian Computer

Little-Endian Computer

Send out an integer 169283078

Receive an integer 68032266!

Page 31: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

31

Solution: Network Byte Order

• Let’s have some regulation!— Network byte order is defined as big-endian byte order— Integers should be sent out in network byte order

• The members sin_port and sin_addr in struct sockaddr_in should be in network byte order— sin_port: TCP or UDP port number, put into the TCP/UDP header— sin_addr: IP address, put into the IP header

• The member sin_family will not be sent out to the network. So it is not necessary to be in network byte order.

• If your application needs to transfer integers between two machines, you should transfer them into network byte order.— You don’t know the type of CPU that executes your program!

Page 32: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

32

Network Byte Order• When sending out an integer

—Transfer it into network byte order by:—u_short htons (u_short host_short);—u_long htonl (u_long host_long);

• After receiving an integer—Transfer it into (local) host byte order by:—u_short ntohs (u_short network_short);—u_long ntohl (u_long network_long);

• Remark:—u_short: unsigned 16-bit integer—u_long: unsigned 32-bit integer

h: host

n: network

s: short

l: long

h-to-n-s

h-to-n-l

n-to-h-s

n-to-h-l

Page 33: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

33

WinSock API

Function Name MeaningWSAStartup Initialize the socket library (Windows only)

WSACleanup Terminate use of socket library (Windows only)

WSAGetLastError Retrieve the specific error code following an unsuccessful socket function call (Windows only)

socket Create a socket used for network communication

connect Connect to a remote peer (client)

closesocket Terminate communication and remove the socket

bind Specify a local IP address and protocol port for a socket

listen Place the socket in passive mode and set the number of incoming TCP connections the system will enqueue (server)

accept Accept the next incoming connection (server)

Page 34: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

34

WinSock API

Function Name Meaningrecv Acquire incoming data from a stream connection or the next incoming

message (mainly for TCP)

recvfrom Receive the next incoming datagram and record its source endpoint address (UDP)

send Send outgoing data or a message (mainly for TCP)

sendto Send an outgoing datagram to a specified endpoint address (UDP)

select Wait until the first of a specified set of sockets becomes ready for I/O

shutdown Terminate a TCP connection in one or both directions

inet_addr Convert IP address in dotted decimal form to internal binary form

inet_ntoa Convert IP address from internal binary form to a text string

gethostbyname Map a host name to an IP address

Page 35: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

35

A TCP Client-Server ExampleCLIENT SIDE SERVER SIDE

WSAStartup()

socket()

connect()

send()

recv()

closesocket()

WSACleanup()

WSAStartup()

socket()

listen()

recv()

send()

closesocket()

WSACleanup()

bind()

accept()

Remark:

The server runs forever. It waits for a new connection on the well-known port, accepts the connection, interacts with the client, and then closes the connection.

Page 36: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

36

A UDP Client-Server Example

socket()

closesocket()

recvfrom()

sendto()

sendto()

recvfrom()

bind()

socket()

process request

data (request)

data (reply)

UDP Client UDP Server

closesocket()

WSACleanup()WSACleanup()

WSAStartup()WSAStartup()

Page 37: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

37

Comparison Between TCP and UDP• Common function calls

—WSAStartup(), WSACleanup()

—socket(), closesocket()

—bind()

• Differences—TCP is connection-oriented, UDP is connectionless

• TCP applications use listen(), accept(), connect() to setup TCP connections

—Data transfer• TCP applications use send() and recv()

• UDP applications use sendto() and recvfrom()

Page 38: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

38

WSAStartup()Programs using WinSock must call WSAStartup() before using sockets. It is needed because the operating system uses dynamically linked libraries (DLLs).

int WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData );

• wVersionRequested : The highest version of Windows Sockets support that the caller can use. The high order byte specifies the minor version (revision) number; the low-order byte specifies the major version number.

• lpWSAData : A pointer to the WSADATA data structure that is to receive details of the Windows Sockets implementation.

WSAStartup() returns zero if successful. Example code:WSADATA wsadata;int err;err = WSAStartup(MAKEWORD(2,2), &wsadata);if (err != 0) return;

Page 39: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

39

WSACleanup()• Once an application finishes using and closing

sockets, it calls WSACleanup() to deallocate all data structures and socket bindings.

• A program usually calls WSACleanup() only when it is completely finished and ready to exit.

int WSACleanup(void);

The return value is zero if the operation was successful. Otherwise, the value SOCKET_ERROR

is returned.

Page 40: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

40

WSAGetLastError()• An application calls the WSAGetLastError function to

retrieve the specific error code following an unsuccessful socket function call.

• An application should call WSAGetLastError immediately after a socket function returns an error indication.—So that you can know what the problem is.

• Windows Sockets Error Codes —http://msdn.microsoft.com/en-us/library/ms740668.aspx

int WSAGetLastError(void);

The return value indicates the error code for this thread's last Windows Sockets operation that failed.

Page 41: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

41

socket()The Windows Sockets socket() function creates a socket.

SOCKET socket ( int af, int type, int protocol );

• af: An address family specification. • type: A type specification for the new socket. The following are the only two type specifications supported for Windows Sockets 1.1: SOCK_STREAM and SOCK_DGRAM. In Windows Sockets 2, some new socket types are introduced.• protocol: A particular protocol to be used with the socket that is specific to the indicated address family. Remark: we usually set it as 0.

If no error occurs, socket() returns a descriptor referencing the new socket. Otherwise, a value of INVALID_SOCKET is returned.

Example code:SOCKET s;s = socket(AF_INET, SOCK_STREAM, 0);if (s == INVALID_SOCKET) { printf(“Error code: %d\n”, WSAGetLastError()); return;}

Page 42: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

42

closesocket()• Once a client or server finishes using a socket, it calls closesocket() to

deallocate it.

• If only one process is using the socket, closesocket() immediately terminates the connection and deallocates the socket.

• If several processes share a socket, closesocket() decrements a reference count and deallocates the socket when the reference count reaches zero.

int closesocket (SOCKET s);

If no error occurs, closesocket() returns zero. Otherwise, a value of SOCKET_ERROR is returned.

Page 43: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

43

Assigning Endpoint Address

At the server side:

#define S_PORT 13

struct sockaddr_in servaddr;

memset(&servaddr, 0, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

servaddr.sin_port = htons(S_PORT);

Remark:

INADDR_ANY represents a wildcard address that matches any of the computer’s IP address.

In winsock2.h:

#define INADDR_ANY (u_long)0x00000000

At the client side:

#define S_PORT 13

struct sockaddr_in servaddr;

memset(&servaddr, 0, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_port = htons(S_PORT);

servaddr.sin_addr.s_addr = inet_addr(argv[1]);

Remark:

inet_addr() takes an ASCII string that contains a dotted decimal address and returns the equivalent IP address in binary.

argv[1] represents the first argument to the command.

The server doesn’t know who will connect to it. It needs to define the local port number only.

The client must provide the IP address and port number of the server.

Page 44: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

44

How to Get the Server Address?• The client software needs to know the server’s

address.• You can:

—Include the address into the source code• Not flexible. If the server’s address is changed, you have to

recompile your source code.

—Require the user to identify the server when invoking the program

• the most popular way

Page 45: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

45

inet_addr(): Parsing an Address• The arguments are stored in character strings

• E.g., when user input an IP address “128.10.2.3”, your program usually receives just a string. You need to transfer this string into an IP address data structure.

unsigned long inet_addr ( const char * cp );

If successful, inet_addr() returns an unsigned long that contains the IPv4 address in binary form using network byte order. Otherwise, inet_addr() returns INADDR_NONE to indicate that the argument does not contain a valid dotted decimal address.

Example code:void main (int argc, char * argv[]) { struct sockaddr_in servaddr; … servaddr.sin_addr.s_addr = inet_addr(argv[1]);}

Page 46: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

46

inet_ntoa(): Output an IP Address• char * inet_ntoa(struct in_addr in);• The inet_ntoa() function takes an Internet address

structure specified by the in parameter and returns an ASCII string representing the address in dot notation as in "a.b.c.d''.

• Good for output!

Example code:char *a;struct sockaddr_in servaddr;…a = inet_ntoa(servaddr.sin_addr);printf(“address is : %s\n”, a);

Page 47: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

47

Looking Up a Domain Name• Internet hosts can be identified by IP address or hostnames.• The Domain Name Service (DNS) provides mapping

between hostname and IP address—E.g.:

• www.hkbu.edu.hk 158.182.4.1• www.google.com 66.249.89.104

• How can we use DNS service?—To enjoy DNS services, you must keep the IP address of a default

DNS server (or more backups), configured by hand or by DHCP.• Check this out by command “ipconfig /all”.

—Every time you need to map a domain name into its corresponding IP address, you call the function gethostbyname().

• It will trigger the OS to contact the DNS server to obtain the IP address.

Page 48: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

48

gethostbyname()• Sometimes one domain name are mapped to a list of IP addresses (e.g., for a

cluster server).• Instead of returning a single IP address, it will return a complicated data structure

“hostent” which can store a list of IP addresses.

struct hostent {char * h_name; /* official host name */char ** h_aliases; /* other aliases */short h_addrtype; /* address type */short h_length; /* length of each address in bytes

*/char ** h_addr_list; /* list of addresses */

#define h_addr h_addr_list[0]};struct hostent * gethostbyname( const char* name);

1. It will return a NULL pointer if error occurs.2. The returned IP address is in network byte order.

Example code:char* server = “www.comp.hkbu.edu.hk”;struct hostent *h;…if ( h = gethostbyname(server) ) memcpy(&servaddr.sin_addr, h->h_addr, h->h_length);

Page 49: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

49

getservbyname() Most client programs must look up the protocol port for the specific service they wish to invoke. To do so, the client invokes library function getservbyname() which takes two parameters: (1) a string that specifies the desired service; (2) a string that specifies the transport protocol being used (i.e., tcp or udp).

struct servent { char * s_name; /* official service name */ char ** s_aliases; /* other aliases */ short s_port; /* port for this service */ char * s_proto; /* protocol to use */};

struct servent getservbyname ( const char * name, const char * proto );

Another similar library function is getprotobyname(). Check it out by yourself.

Example code:struct servent *sptr;if ( sptr = getservbyname (“smtp”, “tcp”) ) { /* port number is now in sptr->s_port */} else { /* error occurred – handle it */}

Page 50: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

50

bind()• When a socket is first created, it has no associated endpoint addresses.• Function bind() can specify the local endpoint address for a socket.

— Usually, a server calls bind() to specify the well-known port at which they will await connections.

— A client can skip bind() and let OS to decide.

int bind(SOCKET s, const struct sockaddr * addr, int addrlen);• s: the socket descriptor• addr: a pointer to the address assigned to the socket• addrlen: the size (in bytes) of the real address structure

Example code:SOCKET s;struct sockaddr_in servaddr;/* fill in the fields of servaddr */…if ( bind(s, (struct sockaddr*)&servaddr, sizeof(servaddr)) == SOCKET_ERROR ) {

/* error handling */}

If no error occurs, bind() returns 0. Otherwise, it returns SOCKET_ERROR.

Page 51: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

51

Choosing Local Address• Local port number

— A server operates at a well-known protocol port address, which all clients must know.

— In general, the client does not care which port it uses as long as the port has no conflict and the port is not assigned to a well-known service.

— For TCP connection, the local port is assigned by the OS during the call of connect() function.

• Local IP address— It’s trivial for most machines that has only one IP address.— But for a machine with multiple IP addresses, it could be more

complicated.

• TCP client software usually leaves the local endpoint address unfilled, and allows TCP/IP module to select the correct local IP address and an unused local port number automatically.

Page 52: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

52

Iterative TCP Server Algorithm 1. Create a socket and bind to the well-known address for the service being

offered.• socket() and bind()

2. Place the socket in passive mode, making it ready for use by a server.• listen()

3. Accept the next connection request from the socket, and obtain a new socket for the connection.

• accept()

4. Repeatedly receive a request from the client, formulate a response, and send a reply back to the client according to the application protocol.

• recv() and send()

5. When finished with a particular client, close the connection and return to step 3 to accept a new connection.

• closesocket()

Page 53: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

53

listen()• TCP server calls listen() to place a socket in passive mode and makes it

ready to accept incoming connections. — A socket in passive mode is used for acceptance of TCP connection request,

not for data transfer.

• To handle multiple clients for the server, listen() tells the operating system to queue the connection requests for the server’s socket.

int listen(SOCKET s, int backlog);• s: the socket descriptor• backlog: the maximum length of the queue of pending connections

Example code:SOCKET listenfd, connfd;struct sockaddr_in servaddr;…bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr));if ( listen(listenfd, 10) == SOCKET_ERROR) { /* error handling */}

If no error occurs, listen() returns 0. Otherwise, it returns SOCKET_ERROR.

Page 54: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

54

accept()• After the server calls listen(), the server can then call accept() to extract the next

incoming connection request from the listening queue.

• Function accept() creates a new socket for each new successful connection request, and returns the descriptor of the new socket to its caller. This new socket is used to transfer data.

SOCKET accept(SOCKET s, struct sockaddr * addr, int *addrlen);• s: the socket descriptor • addr: an optional pointer to a buffer that receives the client’s address• addrlen: an optional pointer to an integer that contains the length of the client’s address structure

Return value:If no error occurs, accept() returns the socket descriptor for the newly accepted socket. Otherwise, a value of INVALID_SOCKET is returned .

Page 55: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

55

accept() Example code:

SOCKET listenfd, connfd;struct sockaddr_in cliaddr;int clilen;…listenfd = socket(AF_INET, SOCK_STREAM, 0);…bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr));listen(listenfd, 10);connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);

Remark:

listenfd is used to accept client connection request.

connfd is used for sending/receiving data.

Page 56: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

56

Server: Two Kinds of Sockets

Client Process

Server Process

socketListening socket

Client Process

Server Process

socket

data datadata

connect()

A new socket returned by

accept()

Page 57: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

57

Server: Two Kinds of Sockets

Browser A Browser B

socket socket

Web Server

Browser C

socket

Remark:

A single listening socket is used by the server to accept incoming connection requests.

Page 58: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

58

TCP Client Algorithm1. Find the IP address and protocol port number of the server with which

communication is desired;2. Allocate a socket;

• socket()

3. Specify that the connection needs an arbitrary, unused protocol port on the local machine, and allow TCP to choose one;• A side-effect of connect()

4. Connect the socket to the server;• connect()

5. Communicate with the server using the application-level protocol;• send() and recv()

6. Close the connection.• closesocket()

Page 59: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

59

connect()• A client calls connect() to establish an active

connection to a remote server.int connect (SOCKET s, struct sockaddr * addr, int addrlen);• s: the socket descriptor• addr: a pointer to the server’s address• addrlen: the length of the server’s address structure

Example code:SOCKET s;struct sockaddr_in servaddr;…s = socket(AF_INET, SOCK_STREAM, 0);/* fill in the structure servaddr */…if ( connect(s, (struct sockaddr *)&servaddr, sizeof(servaddr)) == SOCKET_ERROR ) { /* error handling */}…

If no error occurs, connect() returns 0. Otherwise, it returns

SOCKET_ERROR.

Remark:

servaddr is declared as type struct sockaddr_in.

It is cast into type struct sockaddr when calling connect().

Page 60: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

60

TCP Communications• When TCP is used, TCP module uses a sending buffer and a

receiving buffer for reliable data transmission.—These buffers are inside the OS kernel and different from your

application memory buffer!• For sending out data, send() is used.

—Usually when send() returns, all the data have been put into the send buffer. We can assume that these data will be successfully delivered eventually.

• For receiving data, recv() is used. —But when recv() returns, the number of received bytes could be

different from what you expect (i.e., different from what the other side has sent).

—You must be careful when using recv(). You need to check how many bytes of data have been actually received and then decide what to do next.

Page 61: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

61

TCP: Sending Data • For a TCP connection (SOCK_STREAM), both client and server call

send() to send data and recv() to receive data.

int send(SOCKET s, const char * buf, int len, int flags);

• s: the socket descriptor

• buf: a pointer to the message to be sent out

• len: the length of the message in bytes

• flags: can be 0 or MSG_OOB or MSG_DONTROUTE

Remark:

Each TCP socket has a send buffer in the OS. When we call send(), the OS copies all the data from the application buffer to the socket send buffer. And the TCP module in the OS kernel will handle the data transfer on the background.

1. If the send buffer has enough room, send() will return just after the data copying.

2. If the send buffer has no enough room, send() will block itself until all the data are copied into the send buffer.

If no error occurs, send() returns the total number of bytes sent. Otherwise, a value of SOCKET_ERROR is returned.

Page 62: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

62

TCP: Receiving Data

int recv(SOCKET s, char * buff, int len, int flags);• s: the socket descriptor• buf: a pointer to the buffer to receive incoming data• len: the size of the buffer• flags: can be 0 or MSG_OOB or MSG_PEEK

Each TCP socket also has a receive buffer in the OS to hold received data until it is read by the application (by calling the recv() function). So before calling recv(), an application buffer must be allocated by the user to store the incoming data. Function recv() will copy the incoming data from the OS kernel to the application buffer.

1. If no data has arrived, recv() will block until data arrives;

2. If the incoming data can fit into the application buffer, recv() extracts all the data and returns the number of bytes received;

3. If the incoming data cannot fit into the application buffer, recv() only extracts enough to fill the buffer. It may be necessary to call recv() several times in order to receive the entire message.

4. If the other side closed the socket, recv() will return 0.

Page 63: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

63

Challenges• TCP allows reliable data transmission between two

processes—Data are regarded as byte stream.

—There is no data boundary.

• Problems—The receiver doesn’t know how much data to receive.

—The number of bytes returned by recv() cannot be known in advance.

• Multiple calls of recv() is a common practice. But you don’t know how many times to call recv()!

• Solutions?

Page 64: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

64

Example 1: If Length is Known

/* receiver code */#define BLEN 20000char buf[BLEN];int n, c=0;

for (n = 0; n < BLEN; n += c) { c = recv(s, &buf[n], BLEN-n, 0);}

In this example, we assume the sender will send 20000 bytes to the receiver. But the receiving application may receive data in small chunks.

buf &buf[n]n += c

Question: in reality, how can the client know the length of the incoming data, i.e., 20000 bytes?

Page 65: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

65

Example 2: Connection Closed by Your Peer

/* receiver code */#define BLEN 20000char buf[BLEN];char *bptr;int n, buflen;

bptr = buf;buflen = BLEN;n = recv(s, bptr, buflen, 0);while ((n != SOCKET_ERROR) && (n != 0)) { bptr += n; buflen -= n; n = recv(s, bptr, buflen, 0);}

buf

bptr bptrn

In this example, we assume the sender will send some bytes (no more than 20000) to the receiver and then close the socket.

The receiver will keep on receiving data until the recv() returns 0.

Page 66: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

66

Example 3: A General Solution - Data Encapsulation• The sender sends length + data to the receiver.

—Usually it is enough to use a 32-bit integer for length

—Remember to use Network Byte Order for the integer!

• The receiver extracts length, then allocates memory, then receives the data (see Example 1).

/* sender code */SOCKET sock;int len, m;char *buf;…len = 20000;buf = malloc(len);… /* fill the buf by your data */m = htonl(len);send(sock, &m, sizeof(m), 0);send(sock, buf, len, 0);…

/* receiver code */SOCKET sock;int i, c, n, len;char *buf, *ptr;…ptr = &n; len = sizeof(n);for (i = 0; i < len; i += c) c = recv(sock, &ptr[i], len-i, 0);len = ntohl(n);

buf = malloc(len);for (i = 0; i < len; i += c) c = recv(sock, &buf[i], len-i, 0);

Page 67: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

67

UDP Client Algorithm1. Find the IP address and protocol port number of the server

with which communication is desired;

2. Allocate a socket;

3. Specify that the communication needs an arbitrary, unused protocol port on the local machine, and allow UDP to choose one;

4. Specify the server to which messages must be sent;

5. Communicate with the server using the application-level protocol;

• This usually involves sending requests and awaiting replies

6. Close the socket.

Page 68: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

68

UDP: Sending / Receiving Data• For connectionless service, i.e., UDP (SOCK_DGRAM), sendto() and

recvfrom() are normally used for data transfer.

int sendto(SOCKET s, const char * buff, int buflen, int flags, const struct sockaddr * to, int tolen)

sendto() requires the destination endpoint address as an argument. Why send() doesn’t?

sendto() returns the number of bytes sent if successful, and SOCKET_ERROR to indicate that an error has occurred.

int recvfrom(SOCKET s, char * buff, int buflen, int flags, struct sockaddr * from, int * fromlen)

recvfrom() extracts the next message that arrives at a socket and records the sender’s address.

recvfrom() returns the number of bytes in the message if successful, and SOCKET_ERROR to indicate that an error has occurred.

The receiver doesn’t know who will send him data. Any machine can send data to this receiver if it knows the receiver’s IP and UDP port.

Please study the example codes on Page 7 and 8.

Page 69: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

69

“Connected” UDP• UDP is connectionless.

—When call sendto() and recvfrom(), the peer’s address is included or returned as a parameter.

—An unconnected UDP socket can receive packets from any machine.

• Somehow, there is a “connected” UDP socket—You can call connect() to store the destination’s address in the OS

kernel at the beginning—We can no longer specify the destination’s address—We can call send() to send a message and recv() to receive a response.

Each call to recv() returns one complete message.—Connected UDP socket is still UDP. The only difference with

unconnected UDP socket is the including of destination address information. With this information, the OS will help you to filter out the messages from unknown peers.

Page 70: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

70

More about UDP Programming• Reliability issue

—A client must implement reliability through timeout and retransmission, if reliability is desired.

—Even if your application doesn’t require reliability, it is important to use timeout control because recvfrom() will block forever if the expected incoming packet is lost.

• Flow control issue—UDP module has no flow control (but TCP has).

—A high performance PC can send out tens of thousands of packets per second with a 100Mbps Ethernet. But a very slow PC may be swallowed by so huge UDP traffic! If the slow PC’s CPU is too busy, the UDP receive buffer will be accumulated to full and the new incoming UDP packets will be dropped.

Page 71: 1 Data Communications and Networking Socket Programming Part I: Preliminary Reading: Appendix C - Sockets: A Programmer’s Introduction Data and Computer.

71

More References• Learn by practicing!

—Some example codes are available on the course web site.

—Use WireShark to learn basic socket programming debugging skills.

—Start with some toy programs.

—Finish the course project individually.

• References:—Douglas E. Comer and David L. Stevens, Internetworking with

TCP/IP, Volume III: client-server programming and applications, 1997, Prentice-Hall.

—W. Richard Stevens, Bill Fenner, and Andrew M. Rudoff, UNIX Network Programming, Volume I: The Sockets Networking API, 3rd Edition, 2004, Addison-Wesley.

—Winsock Programming FAQ: http://www.tangentsoft.net/wskfaq/