Client-Server Network Programming Using Sockets With C++

Download Report

Transcript Client-Server Network Programming Using Sockets With C++

Client-Server Network
Programming
Session 1: Introduction to Sockets and socket types
A workshop by
Dr. Junaid Ahmed Zubairi
Department of Computer Science
State University of New York at Fredonia
Workshop Outline
1. Client-Server Mechanisms
2. How the Applications work
3. Introduction to sockets
4. Socket types
5. Programming with sockets
6. Concurrent Processing
7. Programming project
Workshop References
1. “Computer Networking: A Top Down
Approach Featuring the Internet” Kurose
and Ross, Addison Wesley 2001
2. “Internetworking with TCP/IP Vol 3: ClientServer Programming and Applications”
Comer and Stevens, Prentice Hall 2001
3. “Hands on Networking” Doug Comer 2nd
edition Pearson Prentice Hall 2005
4. “An Introduction to Network Programming
with Java” Jan Graba Pearson Addison
Wesley 2003
Client-Server Mechanisms
Let us assume that a person is trying to start
two programs on separate networked
machines (M1 and M2) and these programs
must communicate with each other
When the person starts the first program on
machine M1, this program sends a message
to the program on machine M2
Since the computer works much faster than
human beings, the program on M1 waits a
few milliseconds for response from M2 and
then gives up displaying an error message
Client-Server Mechanisms
Meanwhile, our friend reaches M2 and types
the second program name to start it on M2
The second program waits for a message
from M1 for a few milliseconds and then
concludes that the first program is not active
yet. It displays an error message and exits.
Our friend would keep starting the programs
but they will never be able to communicate.
Client-Server Mechanisms
The solution is to let one program open up
communications and wait indefinitely for a
message from the other program
The first program to start running is called
the server. The server must listen for any
message from the client
The other program is called the client and the
client is supposed to initiate the
communication by sending a message to the
server
Client-server paradigm
Typical network app has two
pieces: client and server
Client:
initiates contact with server
(“speaks first”)
typically requests service from
server,
for Web, client is implemented in
browser; for e-mail, in mail
reader
Server:
provides requested service to
client
e.g., Web server sends requested
Web page, mail server delivers email
application
transport
network
data link
physical
request
reply
application
transport
network
data link
physical
Introduction to Sockets
A machine on the network may be
running various network servers (Web,
Email, FTP, DNS etc.)
Many different clients may contact this
machine, all requesting various services
The machine services the clients
correctly based on the port numbers
Multiplexing/demultiplexing
segment - unit of data
exchanged between
transport layer entities
 aka TPDU: transport
protocol data unit
application-layer
data
segment
header
segment
Ht M
Hn segment
P1
M
application
transport
network
P3
Demultiplexing: delivering
received segments to
correct app layer processes
receiver
M
M
application
transport
network
P4
M
P2
application
transport
network
Multiplexing/demultiplexing
Multiplexing:
gathering data from multiple
app processes, enveloping
data with header (later used
for demultiplexing)
32 bits
source port #
dest port #
other header fields
multiplexing/demultiplexing:
based on sender, receiver
port numbers, IP addresses
 source, dest port #s in
each segment
 well-known port numbers
for specific applications
application
data
(message)
TCP/UDP segment format
Multiplexing/demultiplexing:
examples
host A
source port: x
dest. port: 23
server B
source port:23
dest. port: x
Source IP: C
Dest IP: B
source port: y
dest. port: 80
port use: simple telnet app
Web client
host A
Web client
host C
Source IP: A
Dest IP: B
source port: x
dest. port: 80
Source IP: C
Dest IP: B
source port: x
dest. port: 80
Web
server B
port use: Web server
Well-Known Ports
The application servers listen on well-known
ports or “reserved” ports so that every user
can connect to them.
Some well known ports are as under:
HTTP: 80
FTP: 21
SMTP: 25
POP3: 110
More ports in RFC1700 (www.ietf.org)
Socket programming
Goal: learn how to build client/server application
that communicate using sockets
Socket API
introduced in BSD4.1
UNIX, 1981
explicitly created, used,
released by apps
client/server paradigm
two types of transport
service via socket API:
 unreliable datagram
 reliable, byte streamoriented
socket
a host-local, applicationcreated/owned,
OS-controlled interface
(a “door”) into which
application process can
both send and
receive messages to/from
another (remote or
local) application process
Socket-programming
Socket: a door between application process and
end-end-transport protocol (UDP or TCP)
TCP service: reliable transfer of bytes from one
process to another
controlled by
application
developer
controlled by
operating
system
process
process
socket
TCP with
buffers,
variables
host or
server
internet
socket
TCP with
buffers,
variables
host or
server
controlled by
application
developer
controlled by
operating
system
Socket programming with TCP
Client must contact server
server process must first be
running
server must have created
socket (door) that welcomes
client’s contact
Client contacts server by:
creating client-local TCP
socket
specifying IP address, port
number of server process
When client creates socket:
client TCP establishes
connection to server TCP
When contacted by client,
server TCP creates new socket
for server process to
communicate with client
 allows server to talk with
multiple clients
application viewpoint
TCP provides reliable, in-order
transfer of bytes (“pipe”)
between client and server
Socket API
Each socket is identified by its socket
descriptor
The OS allocates a new data structure
to hold necessary information on
creation of a socket
A passive socket listens for incoming
messages. An active socket is used by a
client to initiate connection
Socket API
For TCP/IP communications, the programs
should use predefined structure
“sockaddr_in”
Major system calls in Socket API are as
follows:
socket() to create a socket
connect() to establish active connection to a
server
send() to transfer data
recv() to receive data
close() to terminate the connection
Sockaddr_in
struct sockaddr_in {
u_char sin_len; //total length
u_short sin_family; //type of address
u_short sin_port; //protocol port no.
struct in_addr sin_addr; //ip address
char sin_zero[8]; //unused
}
Socket API
Client side:
socketconnect sendrecvclose
Server side:
socketbindlistenacceptrecv
sendclose
Programs must #include <sys/types.h>
and <sys/socket.h>
Getting Started with Sockets
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
int main(void)
{
int s;
s = socket(PF_INET, SOCK_STREAM, 0);
printf(“I just got a socket created\n”);
return 1;
}
Getting Started With Sockets
The socket() call takes 3 arguments
socket(domain,type,protocol)

The first argument is the domain.
 PF_INET for network sockets
 PF_UNIX for system sockets

The second argument is the socket type
 SOCK_DGRAM is for UDP socket
 SOCK_STREAM is for TCP socket

The third argument is left 0 so that the system
can select the correct protocol
System returns a descriptor that can be used
to refer to the socket later
Getting Started With Sockets
Once a socket is created, we should be
able to connect to a remote machine
If we are on the client side, we need to
get the server’s IP address and then try
to connect to the server
Client Side
Get remote host information by using the
following statements. Do not forget to
#include <netinet/in.h> and <netdb.h>





struct hostent * ph; //remote host name and info
struct sockaddr_in sa; //holds IP address and protocol port
memset(&sa, 0, sizeof(sa)); //zero out the sa struct
if ((ph = gethostbyname (“www.cs.fredonia.edu”)) == NULL)
{ printf(“error in gethostbyname\n”); exit(1); }
We tried to get the IP address by using DNS
service. If it failed, the program will exit with
a nonzero error code. hostent structure is
defined in netdb.h
Client connects to a web
server







//now ph has the IP address of the server, copy it to sa
memcpy((char *) &sa.sin_addr,ph->h_addr, ph->h_length);
//Fill out the sin_port information by converting the port number to network
byte order
sa.sin_port = htons((u_short) 80);
sa.sin_family = ph->h_addrtype;
if (connect(s, &sa, sizeof(sa) < 0))
{ perror(“connect error\n”);exit(1);}
Network byte order is a neutral order for
sending numerical quantities. It is used
because PC’s store the numbers in opposite
way to mainframes and UNIX workstations.
Client requests a web page
Now client requests a web page from
the server. Let us check out the sample
source code and try to understand as to
what is going on
Client Requests a Web Page
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define BUFLEN 1024
char req[40] = "GET /~zubairi/index.html HTTP/1.0\n\n";
char buf[BUFLEN];
char *bptr;
int n;
int buflen;
int count=0;
main()
{
int s;
struct hostent * ph; //remote host name and info
Sample Source Code
struct sockaddr_in sa; //holds IP address and protocol port
req[39] = '\0';
printf("%s",req);
s = socket(PF_INET, SOCK_STREAM, 0);
printf("Socket was created\n");
memset(&sa, 0, sizeof(sa)); //zero out the sa struct
if ((ph = gethostbyname ("www.cs.fredonia.edu")) == NULL)
{ printf("error in gethostbyname\n"); exit(1); }
//now ph has the IP address of the server, copy it to sa
memcpy((char *) &sa.sin_addr,ph->h_addr, ph->h_length);
Sample Source Code
//Fill out the sin_port information by converting the
//port number to network byte order
sa.sin_port = htons((u_short) 80);
sa.sin_family = ph->h_addrtype;
if (connect(s, &sa, sizeof(sa)) < 0)
{ perror("connect error\n");exit(1);}
else printf("connected to web server\n");
bptr = buf;
buflen = BUFLEN;
if (send (s, req, strlen(req), 0)<=0) perror("send error\n");
else printf("Sent to the server\n");
Sample Source Code
printf("Now starting to receive\n");
While ( (n = recv(s,bptr,buflen,0) ) > 0)
{
printf("Still receiving\n");
count++;
}
if (!count) printf("Error in receive\n");
else printf("received all \n");
printf("%s\n",bptr);
}
Web client code
C strings are null terminated (\0)
Request to get the web page is sent to
the web server at port 80
Source code receives and displays all
pieces received
You can also receive and display piece
by piece as shown
Web client code
while ( (n = recv(s,bptr,buflen,0) ) > 0)
{
printf("%s",bptr); //print the received data
bptr = bptr+n; //advance the pointer to buffer beyond received bytes
buflen = buflen –n; //reduce the available buffer length accordingly
}
TCP Server
Following is an example server program
from Dr. Comer’s ftp site. It waits for
connection from the client, sends a
short message to it and then closes
connection
TCP Server Initialization
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#define PROTOPORT 5193 // port number
#define QLEN 6
// size of request queue
int visits
= 0;
// counts client connection
TCP Server Initialization
main(argc, argv)
int argc;
char *argv[];
{
struct
hostent *ptrh; /* pointer to a host table entry
*/
struct
protoent *ptrp;
/* pointer to a protocol table entry */
struct
sockaddr_in sad; /* structure to hold server's address */
struct
sockaddr_in cad; /* structure to hold client's address */
int
sd, sd2; /* socket descriptors
*/
int
port;
/* protocol port number
*/
int
alen;
/* length of address*/
char
buf[1000]; /* buffer for string the server sends*/
Setting Port No. for TCP Server
memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure
sad.sin_family = AF_INET;
/* set family to Internet */
sad.sin_addr.s_addr = INADDR_ANY; /* set the local IP address
/* Check command-line argument for protocol port and extract it
if (argc > 1) {
/* if argument specified */
port = atoi(argv[1]);
/* convert argument to binary
} else port = PROTOPORT;
/* else use default port number*/
if (port > 0)
/* test for illegal value
sad.sin_port = htons((u_short)port);
else { /* print error message and exit
*/
fprintf(stderr,"bad port number %s\n",argv[1]);
exit(1);
}
*/
*/
*/
*/
*/
Map Protocol and Create a Socket
/* Map TCP transport protocol name to protocol number */
if ( ((int)(ptrp = getprotobyname("tcp"))) == 0) {
fprintf(stderr, "cannot map \"tcp\" to protocol
number");
exit(1);
}
/* Create a socket */
sd = socket(PF_INET, SOCK_STREAM, ptrp->p_proto);
if (sd < 0) {
fprintf(stderr, "socket creation failed\n");
exit(1);
}
Bind to Socket and Set Queue
/* Bind a local address to the socket */
if (bind(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
fprintf(stderr,"bind failed\n");
exit(1);
}
/* Specify size of request queue */
if (listen(sd, QLEN) < 0) {
fprintf(stderr,"listen failed\n");
exit(1);
}
Accept Requests and Fulfill
while (1) {
alen = sizeof(cad);
if ( (sd2=accept(sd, (struct sockaddr *)&cad, &alen)) < 0) {
fprintf(stderr, "accept failed\n");
exit(1);
}
visits++;
sprintf(buf,"This server has been contacted %d
time%s\n",
visits,visits==1?".":"s.");
send(sd2,buf,strlen(buf),0);
close(sd2);
}
}
Lab 1
First compile and run the server
Next modify the client code to set the IP
address of the server to the correct value and
port number to the correct port.
Now the client can be started
Each time the client runs, the server keeps
incrementing the count of clients served