You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

152 lines
4.5 KiB
Markdown

3 weeks ago
# Network
TODO
## Code Examples
First let's try writing some **UDP** C program under [Unix](unix.md). Remember that UDP is the unreliable protocol, so it's possible our messages may get lost or distorted, but in programs that can handle some losses this is the faster and more KISS way. Our program will be peer-to-peer, it will create two sockets, one listening and one sending. It will make a few message exchange turns, in each turn it will send something to its partner, it will check if it itself got any message and then will wait for some time before the next round. Note that we will use a non-blocking receiving socket, i.e. checking if we have any messages won't pause our program if there is nothing to be received, we'll simply move on if there is nothing (that's how realtime games may do it, but other kinds of server may rather a use blocking socket if they intend to do nothing while waiting for a message). Also pay attention to the fact that the program will choose its port number based on a one letter "name" we give to the program -- this is so that if we test the programs on the same computer (where both will have the same IP address), they will choose different ports (different processes on the same computer cannot of course use the same port).
```
#include <stdio.h>
5 days ago
#include <stdlib.h> // for exit
3 weeks ago
#include <unistd.h> // for sleep
#include <arpa/inet.h>
#include <sys/socket.h>
#define BUFFER_LEN 8
#define PORT_BASE 1230
// run as ./program partner_addr partner_letter my_letter
char buffer[BUFFER_LEN + 1]; // extra space for zero terminator
char name; // name of this agent (single char)
5 days ago
int sock = -1; // socket, for both sending and receiving
3 weeks ago
void error(const char *msg)
{
printf("%c: ERROR, %s\n",name,msg);
5 days ago
if (sock >= 0)
close(sock);
3 weeks ago
exit(1);
}
int main(int argc, char **argv)
{
if (argc < 4)
error("give me correct arguments bitch");
name = argv[3][0];
char *addrStrDst = argv[1];
int portSrc = PORT_BASE + name, // different name => different port
portDst = PORT_BASE + argv[2][0];
struct sockaddr_in addrSrc, addrDst;
5 days ago
sock = socket(AF_INET,SOCK_DGRAM | SOCK_NONBLOCK,IPPROTO_UDP);
3 weeks ago
5 days ago
if (sock < 0)
error("couldn't create socket");
3 weeks ago
addrSrc.sin_family = AF_INET;
5 days ago
addrSrc.sin_port = htons(portSrc); // convert port to netw. endianness
3 weeks ago
addrSrc.sin_addr.s_addr = htonl(INADDR_ANY);
5 days ago
if (bind(sock,(struct sockaddr *) &addrSrc,sizeof(addrSrc)) < 0)
error("couldn't bind socket");
3 weeks ago
addrDst.sin_family = AF_INET;
addrDst.sin_port = htons(portDst);
5 days ago
if (inet_aton(addrStrDst,&addrDst.sin_addr) == 0)
3 weeks ago
error("couldn't translate address");
printf("%c: My name is %c, listening on port %d, "
"gonna talk to %c (address %s, port %d).\n",
name,name,portSrc,argv[2][0],addrStrDst,portDst);
for (int i = 0; i < 4; ++i)
{
printf("%c: Checking messages...\n",name);
5 days ago
int len = recv(sock,buffer,BUFFER_LEN,0);
3 weeks ago
if (len > 0)
{
buffer[len] = 0;
printf("%c: Got \"%s\"\n",name,buffer);
}
else
printf("%c: Nothing.\n",name);
for (int j = 0; j < BUFFER_LEN; ++j) // make some gibberish message
buffer[j] = 'a' + (name + i * 3 + j * 2) % 26;
printf("%c: Sending \"%s\"\n",name,buffer);
5 days ago
if (sendto(/*sockOut*/sock,buffer,BUFFER_LEN,0,
3 weeks ago
(struct sockaddr *) &addrDst,sizeof(addrDst)) < 0)
printf("%c: Couldn't send it!\n",name);
printf("%c: Waiting...\n",name);
usleep(2000000);
}
printf("%c: That's enough, bye.\n",name);
5 days ago
close(sock);
3 weeks ago
return 0;
}
```
We can test this for example like this:
```
./program 127.0.0.1 A B & { sleep 1; ./program 127.0.0.1 B A; } &
```
Which may print out something like this:
```
B: My name is B, listening on port 1296, gonna talk to A (address 127.0.0.1, port 1295).
B: Checking messages...
B: Nothing.
B: Sending "oqsuwyac"
B: Waiting...
A: My name is A, listening on port 1295, gonna talk to B (address 127.0.0.1, port 1296).
A: Checking messages...
A: Nothing.
A: Sending "nprtvxzb"
A: Waiting...
B: Checking messages...
B: Got "nprtvxzb"
B: Sending "rtvxzbdf"
B: Waiting...
A: Checking messages...
A: Got "rtvxzbdf"
A: Sending "qsuwyace"
A: Waiting...
B: Checking messages...
B: Got "qsuwyace"
B: Sending "uwyacegi"
B: Waiting...
A: Checking messages...
A: Got "uwyacegi"
A: Sending "tvxzbdfh"
A: Waiting...
B: Checking messages...
B: Got "tvxzbdfh"
B: Sending "xzbdfhjl"
B: Waiting...
A: Checking messages...
A: Got "xzbdfhjl"
A: Sending "wyacegik"
A: Waiting...
B: That's enough, bye.
A: That's enough, bye.
```
TODO: TCP