Sockets A popular API for client-server interaction.

22
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.

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

See socket code examples

Check out the lab activity on the Course Resources

part of the web page

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

Additional considerations

• Setting up and launching a server on your OS

• How many simultaneous servers can run

• How to handle queues of clients waiting for service

• These and many others are addressed in CS611