Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in...

23
Systems Programming/ C and UNIX Alice E. Fischer October 30, 2017 Alice E. Fischer Systems Programming – Lecture 11. . . 1/23 October 30, 2017 1 / 23

Transcript of Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in...

Page 1: Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in paragraphs. Each paragraph starts with a comment that describes its purpose. This

Systems Programming/ C and UNIX

Alice E. Fischer

October 30, 2017

Alice E. Fischer Systems Programming – Lecture 11. . . 1/23 October 30, 2017 1 / 23

Page 2: Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in paragraphs. Each paragraph starts with a comment that describes its purpose. This

Outline

1 SocketsRemote CommunicationSystem-Defined Socket Types

2 Using the Socket ClassSocket.hpp and Socket.cppclient.cpp: the Clientserver.cpp: Serving Multiple Clients

3 Using the Connection

Alice E. Fischer Systems Programming – Lecture 11. . . 2/23 October 30, 2017 2 / 23

Page 3: Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in paragraphs. Each paragraph starts with a comment that describes its purpose. This

Sockets

Sockets

Serving a Single Client

IncompatibilitiesA Sockets Header File

client.c: the Clientserver.c: Serving One Client

Alice E. Fischer Systems Programming – Lecture 11. . . 3/23 October 30, 2017 3 / 23

Page 4: Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in paragraphs. Each paragraph starts with a comment that describes its purpose. This

Sockets Remote Communication

Remote Communication Problems

Communication from one computer to another raises several problems.

To reach a computer via the internet, the remote computer’s ipaddress must be registered with a domain name server.

Connections coming into a computer from the internet must go to aspecific port.

All of the usual services work through specific well-known ports. Forexample ssh uses TCP port 22, HTTP uses port 80, and HTTPS usesport 443.

If you write your own server, and want it to be available to anyone,anywhere, you must choose a port number and publish it to yourclients.

Advice: avoid port numbers below 1024 because many are used bysystem programs

Alice E. Fischer Systems Programming – Lecture 11. . . 4/23 October 30, 2017 4 / 23

Page 5: Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in paragraphs. Each paragraph starts with a comment that describes its purpose. This

Sockets Remote Communication

Incompatibilities

Connecting would be hard enough if every computer were the same andran the same system. But, they aren’t and they don’t.

All systems can, at least, run the same communication protocol: IP

But the definitions of different system types are different for Macsthan for Linux.

The byte-order is different on little-endian and big-endian machines.

The length of an integer might be different on different hardware.

We are transitioning from 4-byte IP addresses to 6-byte addresses

Therefore, EVERYTHING must be done at an abstract level, using systemcalls, and not depending on the representation of anything.

Alice E. Fischer Systems Programming – Lecture 11. . . 5/23 October 30, 2017 5 / 23

Page 6: Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in paragraphs. Each paragraph starts with a comment that describes its purpose. This

Sockets Remote Communication

The Nature of the Code

After every system call, your program must check for error codes beingreturned. Otherwise, you will never get it debugged.

The Socket class, server, and client code are, basically, a series ofsystem calls. In addition, the client and server in this demo both havesmall application-centered portions.

The code is built in paragraphs. Each paragraph starts with acomment that describes its purpose.

This is followed by a system call.

Then comes the test for errors.

Finally, debugging output is printed.

So out of every five lines of code, only one line does part of the basic task.The rest is preparation or checking or output.

Alice E. Fischer Systems Programming – Lecture 11. . . 6/23 October 30, 2017 6 / 23

Page 7: Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in paragraphs. Each paragraph starts with a comment that describes its purpose. This

Sockets System-Defined Socket Types

struct sockaddr_in

This type is used only to bundle-up the information needed toinitialize a socket.

It is not the type of a socket and it probably is not the type of part ofa socket, but the info in it is needed to initialize a socket.

It is a structure used to transport information “over the wall” fromthe application program into the kernel or back out to the application.

struct sockaddr_in {

//__uint8_t sin_len; // On Mac but not in Linux

sa_family_t sin_family;

in__t sin_port;

struct in_addr sin_addr;

char sin_zero[8];

};

Alice E. Fischer Systems Programming – Lecture 11. . . 7/23 October 30, 2017 7 / 23

Page 8: Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in paragraphs. Each paragraph starts with a comment that describes its purpose. This

Sockets System-Defined Socket Types

struct in_addr

Type struct in_addr is the type of one member of asockaddr_in.

We need the type only once, on Socket.cpp line 24.

struct in_addr {

in_addr_t s_addr; // unsigned int (32 bit).

};

typedef struct pollfd toPoll;

Alice E. Fischer Systems Programming – Lecture 11. . . 8/23 October 30, 2017 8 / 23

Page 9: Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in paragraphs. Each paragraph starts with a comment that describes its purpose. This

Sockets System-Defined Socket Types

struct sockaddr

The type sockaddr is the generic C base type from which specific Csocket types derive.

The Unix system functions are defined in terms of sockaddr.

Class derivation does not exist in C, so casts must be used to convertfrom the derived type sockaddr_in to the base type sockaddr everytime you make a system call.

struct sockaddr {

unsigned short sa_family; // address family, AF_xxx

char sa_data[14]; // IP address

};

Alice E. Fischer Systems Programming – Lecture 11. . . 9/23 October 30, 2017 9 / 23

Page 10: Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in paragraphs. Each paragraph starts with a comment that describes its purpose. This

Sockets System-Defined Socket Types

toPoll: typedef name for struct pollfd

toPoll is the type of the elements in the polling table.

When poll() is called, the list of pending events on each socket iscopied into the corresponding line in the polling table (ufds[fd]).

Then the polling loop examines each line in the ufds table andservices the pending requests.

struct pollfd {

int fd; // file descriptor

short events; // types of events to service

short revents; // unprocessed events

};

Alice E. Fischer Systems Programming – Lecture 11. . . 10/23 October 30, 2017 10 / 23

Page 11: Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in paragraphs. Each paragraph starts with a comment that describes its purpose. This

Sockets System-Defined Socket Types

struct hostent

A struct for communicating IP addresses and their associatedinformation.

The type of the object returned by gethostbyname().

Called by the client to get the IP address of the application serverfrom the domain name server.

struct hostent { // Used only in the client

char *h_name; // official name of host

char **h_aliases; // alias list

int h_addrtype; // host address type

int h_length; // length of address

char **h_addr_list; // list of addrs from name server

};

Alice E. Fischer Systems Programming – Lecture 11. . . 11/23 October 30, 2017 11 / 23

Page 12: Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in paragraphs. Each paragraph starts with a comment that describes its purpose. This

Using the Socket Class Socket.hpp and Socket.cpp

Socket.hpp

The purpose of this class is to hide all the nitty-gritty details of usingsockets inside a reusable type. The major functions are:

A default constructor that initializes two of the members of thesockaddr_in.

In this application, we are using only internet sockets (AF_INET) andbyte stream I/O (SOCK_STREAM), so the constructor initializesthose parts of the socket.

The function listen() is provided to initialize the remaining parts ofa server socket.

The function connect() is provided to initialize the remaining partsof a client socket.

These two functions “wrap” the system calls ::listen() and::connect(). Details about how connections are made are hiddeninside the class functions.

Alice E. Fischer Systems Programming – Lecture 11. . . 12/23 October 30, 2017 12 / 23

Page 13: Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in paragraphs. Each paragraph starts with a comment that describes its purpose. This

Using the Socket Class Socket.hpp and Socket.cpp

Socket.hpp – Continued

There are two data members:

a sockaddr_in structure used to communicate with the kernel socket.a copy of the file descriptor, used for debugging printouts.

Routine function members include:

Three getters: for the fd, the port, and the IP address.Two functions to make debugging possible: one to get the peerinformation, the other to get the new port number after a client ishanded off to a different socket.Two print functions: one to print the socket itself, the other to print itspeer socket.An inline definition of the output operator to allow us to use“cout <<” to print sockets.

Alice E. Fischer Systems Programming – Lecture 11. . . 13/23 October 30, 2017 13 / 23

Page 14: Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in paragraphs. Each paragraph starts with a comment that describes its purpose. This

Using the Socket Class Socket.hpp and Socket.cpp

Socket.cpp: listen()

There are three steps to prepare a server socket to receive clients:

Pack a suitcase to send to the kernel socket. Contents: the protocoland port number to use, and the willingness to accept connectionsfrom any computer.

Call the system bind() function. This sends the suitcase to the kernelsocket where the information is used to initialize the socket.

For debugging, refresh() is called here to fetch the actual socketinfo from the kernel for display on the next line.

Finally, we call ::listen() to accept callers on the socket’s fd. Thewaiting queue is limited to 2 callers here. In reality, the limit would belarger.

Alice E. Fischer Systems Programming – Lecture 11. . . 14/23 October 30, 2017 14 / 23

Page 15: Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in paragraphs. Each paragraph starts with a comment that describes its purpose. This

Using the Socket Class Socket.hpp and Socket.cpp

Socket.cpp: connect()

These are three steps in making a connection:

You have to know the url of the server or use “localhost”.gethostbyname(serverUrl) accesses the domain name server,which will look up the url in a series of domains and return ahostent object that contains the server’s IP address. This is returnedas one long string.

The first IP-address in the string is the one we need. This must becopied (memmove) into the client’s member variable, suitcase.

Then the rest of the fields must be copied into the suitcase: theaddress family (AF_INET, for an internet socket) and the portnumber.

Finally, ::connect() uses the suitcase to finish initializing the socket.

The call on refresh() will bring back the actual port this client willuse to talk to the server. We then display this info.

Alice E. Fischer Systems Programming – Lecture 11. . . 15/23 October 30, 2017 15 / 23

Page 16: Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in paragraphs. Each paragraph starts with a comment that describes its purpose. This

Using the Socket Class client.cpp: the Client

The Client’s Job

Line numbers refer to the code in client.cpp.

(12–14) This demo client takes a server name and port number fromthe command line. These things are often hard-coded, but flexibilityis a big help during debugging.

(15–18) The file named on the command line is data for the demoapplication

(27) After processing the command line, the client creates a socket.

(28–29) Then it connects to the server and prints info for theoperator.

(32–34) It might need to wait in the server’s queue, but eventuallygets an ACK from the server.

(38–48) Once connected, it does its job.

(51) And finally quits.

Alice E. Fischer Systems Programming – Lecture 11. . . 16/23 October 30, 2017 16 / 23

Page 17: Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in paragraphs. Each paragraph starts with a comment that describes its purpose. This

Using the Socket Class server.cpp: Serving Multiple Clients

The Server’s Job: server2.cpp

(19) This demo server takes a port number from the command line.Normally, a fixed port number is used. However, during debugging itis very helpful to have a flexible port # because the system takes awhile to clean up its own tables after you terminate a server.

(28–30) Prepare the polling table. Declare the polling table to belong enough for the welcome socket + the maximum number ofclients we will accept.

The pointer worker is set to the first worker socket to promote codeclarity in the doWelcome() function. The pointer welcome is set tothe welcome socket.

(40) Create an uninitialized welcome socket.

(41–42) Call listen( port ) to initialize the welcome socket, thenrecord the fd in our local variable welcomeFd.

(57) Start polling.

Alice E. Fischer Systems Programming – Lecture 11. . . 17/23 October 30, 2017 17 / 23

Page 18: Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in paragraphs. Each paragraph starts with a comment that describes its purpose. This

Using the Socket Class server.cpp: Serving Multiple Clients

The Server’s Job: the Polling Loop

(57–87) Servers are written as endless loops.

(58) Poll all of the sockets (the fd’s in the polling table) to bring thecurrent collection of pending events into the revents column of thepolling table. Of course, check for malfunctions.

(65–71) Check for an event on the welcome socket. If found, and ifthe server is ready for an added client, perform doWelcome().Otherwise, the client must wait in the queue until either the serveraccepts it or it times out or gives up.

(76–83) Check, in turn, for events on the worker sockets. If an eventis found, call doService() to process the message.

(79–81) doService() returns a -1 if there is a problem: eof, a clientsocket disappeared, the client hung up, or there was a hardware readerror. In this case, the dead fd is removed from the polling table.

(85) Set the welcome socket to refuse more connections if the pollingtable is full.

Alice E. Fischer Systems Programming – Lecture 11. . . 18/23 October 30, 2017 18 / 23

Page 19: Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in paragraphs. Each paragraph starts with a comment that describes its purpose. This

Using the Socket Class server.cpp: Serving Multiple Clients

server2.cpp: doWelcome()

Control comes here when a new client is waiting and there is space for it inthe table.

(93) The second parameter is an in/out parameter that will beincremented in this function if a new client is actually accepted. Wedownload it here, for local use, and upload it in line 113.

(94–95) A new sockaddr_in is allocated to receive informationduring the connection process.

(97–101) We try to accept the connection and return to the mainserver loop if no new socket is installed in the file table. In that case,the number of active clients is not incremented.

(105–107) If accept() succeeded, we install the new client in thenext line of the polling table.

(110–111) The connection is ready. We send confirmation to theclient.

Alice E. Fischer Systems Programming – Lecture 11. . . 19/23 October 30, 2017 19 / 23

Page 20: Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in paragraphs. Each paragraph starts with a comment that describes its purpose. This

Using the Socket Class server.cpp: Serving Multiple Clients

server2.cpp: doService()

Control comes here when a client has sent a message to the server. Toprocess it:

(123) Mask the revents to get only the POLLIN events.

(124) If one exists, read the message.

(126–129) If the message has at least one byte, add a null terminatorto make a proper C-string and print it out. In a real application, theserver would process the client request here.

Alice E. Fischer Systems Programming – Lecture 11. . . 20/23 October 30, 2017 20 / 23

Page 21: Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in paragraphs. Each paragraph starts with a comment that describes its purpose. This

Using the Socket Class server.cpp: Serving Multiple Clients

Removing a Dead Socket

Sometimes we must close a socket and remove one client from the list:

(131–134) An end-of-file happens when a client terminates normally.

(135–138) A client can just disappear.

(144-148) Or, maybe the client sent a hangup signal, which weidentify by masking the revents for POLLHUP .

(140) An unexpected error condition causes the server to abort.

When we see that a client is gone, we must remove it from both the filetable and the polling table.

(133, 137, 146) We close the socket here in the doService()

function: close(p->fd);

Then we return to the polling loop with a signal that a client hasdied: retval = -1;

(78–79) The -1 return value will cause the faulty fd to be removedfrom the polling table.

Alice E. Fischer Systems Programming – Lecture 11. . . 21/23 October 30, 2017 21 / 23

Page 22: Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in paragraphs. Each paragraph starts with a comment that describes its purpose. This

Using the Connection

Other Ways to Use a Connection

For messages that are simple constants (ACK, NACK) or just strings,it makes sense to use only the low-level read and write.

For more complex messages, such as tables of numeric values, weneed something more than read() and write(). Manual inputconversion is simply too painful and error prone.

There are two ways to do this:

Wrap a C-stream around the file descriptor and use the stream. Thismakes sense if information only flows one way through the connection.Create a local output stringstream and use it with the C++ <<operator to format and pack the numbers into a C++-string, then sendthe string’s .data() through the connection using write().

Similarly, use read() at the receiving end to bring the message into abuffer. Then wrap an input stringstream around the buffer and use >>to unpack the information.

Alice E. Fischer Systems Programming – Lecture 11. . . 22/23 October 30, 2017 22 / 23

Page 23: Systems Programming/ C and UNIXeliza.newhaven.edu/sysprog/attach/L8-sockets.pdfThe code is built in paragraphs. Each paragraph starts with a comment that describes its purpose. This

Using the Connection

Evaluation of the Polling Program

If the server’s response to a message will take any substantial amountof time, it should fork off a worker process to handle the workerconnection. In this demo, the server just reads and prints a line oftext, and it was not necessary to use fork.

According to our local expert (Prof. Yang Richard Yang at Yale)polling of this sort is the right way to achieve high performance.

A polling loop can ensure that every active client gets a fair share ofthe server’s attention.

The same job could be done using threads, instead. However, usingthreads causes the thread-scheduler to decide who to service next.Neither the OS nor the programmer can impose any order on thescheduling. Fairness suffers.

A modest number of threads could be combined with polling to takeadvantage of multi-core architecture.

Alice E. Fischer Systems Programming – Lecture 11. . . 23/23 October 30, 2017 23 / 23