Sockets A popular API for client-server interaction.
-
date post
20-Dec-2015 -
Category
Documents
-
view
236 -
download
3
Transcript of Sockets A popular API for client-server interaction.
Complete view of a socket
Application
Presentation
Session
Transport
Network
Data Link
Physical
Application
Presentation
Session
Transport
Network
Data Link
Physical
Applications talkto each other viaAPIs like sockets.Sockets provide theinterface to theother layers.
Programmer View of a socket
Application Application
socket
The networking aspects of a socket are transparent
Similar to writing to and reading from a file
137.155.2.12/7055
IP PORT
137.155.2.20/1234
IP PORT
serverclient
Socket API
• Three popular variations– berkley - older outdated unix API– TLI - newer unix version – winsock - microsoft
• All very similar
• Most examples in c but available in other languages
General Approach
SERVERCLIENT
Sets up a connection to wait for client (port)
Asks for connectionto server port Responds & sets up
a different connectionfor the dialog
Client asks for service
Server respondstime
SERVERCLIENT
Sets up a connection to wait for client (port)
Asks for connectionto server port
Responds & sets up a different connection for the dialog
Client asks for service Server responds
time
/* get an internet domain socket */if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
/* bind the socket to the port number */if (bind(sd, (struct sockaddr *) &sin, sizeof(sin)) == -1) {
/* show that we are willing to listen */if (listen(sd, 5) == -1) {
/* grab an Internet domain socket */if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
/* connect to PORT on HOST */if (connect(sd,(struct sockaddr *) &pin, sizeof(pin)) == -1) {
/* wait for a client to talk to us */if ((sd_current = accept(sd, (struct sockaddr *) &pin, &addrlen)) == -1) {
/* send a message to the server PORT on machine HOST */if (send(sd, argv[1], strlen(argv[1]), 0) == -1) {
/* wait for a message to come back from the server */ if (recv(sd, dir, DIRSIZE, 0) == -1) {
/* get a message from the client */ if (recv(sd_current, dir, sizeof(dir), 0) == -1) {
/* get the directory contents */ read_dir(dir); /* acknowledge the message, reply w/ the file names */if (send(sd_current, dir, strlen(dir), 0) == -1) {
#define PORT 0x1234#define DIRSIZE 8192
main(){ char dir[DIRSIZE]; int sd, sd_current, cc, fromlen, tolen; int addrlen; struct sockaddr_in sin; struct sockaddr_in pin; /* get an internet domain socket */ if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");exit(1);
}
/* complete the socket structure */ memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = htons(PORT);
/* bind the socket to the port number */ if (bind(sd, (struct sockaddr *) &sin, sizeof(sin)) == -1) {
perror("bind");exit(1);
}
/* show that we are willing to listen */ if (listen(sd, 5) == -1) {
perror("listen");exit(1);
}
/* wait for a client to talk to us */ if ((sd_current = accept(sd, (struct sockaddr *) &pin, &addrlen)) == -1) {
perror("accept");exit(1);
}
/* get a message from the client */ if (recv(sd_current, dir, sizeof(dir), 0) == -1) {
perror("recv");exit(1);
}
/* get the directory contents */ read_dir(dir);
/* acknowledge the message, reply w/ the file names */ if (send(sd_current, dir, strlen(dir), 0) == -1) {
perror("send");exit(1);
}
/* close up both sockets */ close(sd_current); close(sd); /* give client a chance to properly shutdown */ sleep(1);}
SERVER
CLIENT#define PORT 0x1234 /* REPLACE with your server machine name*/#define HOST "america3"#define DIRSIZE 8192
main(argc, argv)int argc; char **argv;{ char hostname[100]; char dir[DIRSIZE]; int sd; struct sockaddr_in sin; struct sockaddr_in pin; struct hostent *hp;
strcpy(hostname,HOST); if (argc>2) { strcpy(hostname,argv[2]); }
/* go find out about the desired host machine */ if ((hp = gethostbyname(hostname)) == 0) {
perror("gethostbyname");exit(1);
}
/* fill in the socket structure with host information */ memset(&pin, 0, sizeof(pin)); pin.sin_family = AF_INET; pin.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr; pin.sin_port = htons(PORT);
/* grab an Internet domain socket */ if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");exit(1);
}
/* connect to PORT on HOST */ if (connect(sd,(struct sockaddr *) &pin, sizeof(pin)) == -1) {
perror("connect");exit(1);
}
/* send a message to the server PORT on machine HOST */ if (send(sd, argv[1], strlen(argv[1]), 0) == -1) {
perror("send");exit(1);
}
/* wait for a message to come back from the server */ if (recv(sd, dir, DIRSIZE, 0) == -1) { perror("recv"); exit(1); }
/* spew-out the results and bail out of here! */ printf("%s\n", dir);
close(sd);}
Disconnect between Sending and Receiving
CLIENT SERVER
char one[]=“one”; char three[]=“3”;if (send(sd, one, 3, 0) == -1) {..if (send(sd, three, 1, 0) == -1) {..
one
3
OS
3one
(3eno)
3oneChar recvbuf[100]if (recv(sd_current, recvbuf, 100, 0) ...
3one
A question of how the two synchronizetheir respective activities!
Not what you expect!CLIENT SERVER
char one[]=“one”; char three[]=“3”;
if (send(sd, one, 3, 0) == -1) {..
if (send(sd, three, 1, 0) == -1) {..
if (send(sd, one, 3, 0) == -1) {..
if (send(sd, three, 1, 0) == -1) {..
Char recvbuf[100]
if (recv(sd_current, recvbuf, 100, 0) …
if (recv(sd_current, recvbuf, 100, 0) ...
if (recv(sd_current, recvbuf, 100, 0) ...
if (recv(sd_current, recvbuf, 100, 0) ...
NOT a recv for every send!(but not as bad as you think)
Something like thisCLIENT SERVER
char one[]=“one#”; char three[]=“3#”;
if (send(sd, one, 4, 0) == -1) {..
if (send(sd, three, 2, 0) == -1) {..
if (send(sd, one, 4, 0) == -1) {..
if (send(sd, three, 2, 0) == -1) {..
Char recvbuf[100]
bool notdone=true;
while (notdone) { if (recv(sd_current, recvbuf, 100, 0) … // iterate char by char if (recvbuf[i] == “#”) notdone = false; // only read when you exhaust all // of the recvbuff
……...
Actually like if (i==bufflen-1) if (recv…. else i++;
Framing!
Message1Message2Message3
Should be sent as
Message1#Message2#Message3#
And will bereceived as
Message1#Message2#Message3#
Sometimes the application is less demanding! When theinput is predictable in both size andnature of data (like 230 programs)
C issues
• (Main) routine / parameter declaration– main(argc, argv)– int argc; char **argv;– {
• Parameters by reference– int addone(a)– int *a;– {…}– called by x=7; addone (&x)
• I/O– scanf (“%d %d”,%x,%y)– printf (“Value of x is %d and y is %d”,&x,&y);
Adapting the example to your problem
• Setup and disconnect is very similar
• Interaction is not as simple as the example
• read/write are basically executed in your main loop.
Using C++
• No standard library
• A library available online from Rob Tougher .. Linux Gazette
• See– www.pcs.cnu.edu/~dgame/sockets/socketsC+
+/sockets.html
How about java?
• Good support in java
• Will not be covered (at least now)
• You’re encouraged to investigate on your own as CS611 will use java extensively
Fundamental differencewith your programming
experience• Your programs have predictable input
output sequences.
• Typically defined by order of data in a file or which button was clicked.
• Can NOT control order in which peer queries or responds.
• Requires an event-driven paradigm
Event-driven apps
While (NOT A TERMINATE EVENT)get next eventif a reasonable event occurred
process itelse
error or terminate
Consider deadlocks: A waits for B to send a message XB waits for A to send message Yneither does -> deadlock!
Like windows programs!
Will address this more later when we cover protocols.
Problems with socket apps
• Timing problems are new for you
• Apps typically will deadlock
• Since input is less predictable, harder to debug.
• Will need to send/get info through socket and echo to a standard output device whatever is sent/read to aid in debugging
Non-socket APIs
• Other than the three types of sockets, one will typically find RPC in use.
• RPC stands for Remote Procedure Call
• RPC effectively extracts a function from your code and runs it on another machine
X = sqrt(y)Calc sqrt(y)
return results
y
x