dist intro client/server code

This commit is contained in:
Remzi Arpaci-Dusseau
2019-05-30 12:32:20 -05:00
parent acd67a3a42
commit 7f7c16cd40
6 changed files with 199 additions and 0 deletions

20
dist-intro/Makefile Normal file
View File

@@ -0,0 +1,20 @@
CC := gcc
CFLAGS := -Wall -Werror
SRCS := client.c \
server.c
OBJS := ${SRCS:c=o}
PROGS := ${SRCS:.c=}
.PHONY: all
all: ${PROGS}
${PROGS} : % : %.o Makefile
${CC} $< -o $@ udp.c
clean:
rm -f ${PROGS} ${OBJS}
%.o: %.c Makefile
${CC} ${CFLAGS} -c $<

17
dist-intro/README.md Normal file
View File

@@ -0,0 +1,17 @@
# Distributed Systems: Introduction
A simple UDP client and server:
- `client.c`: example client code, sends a message to the server and waits for a reply
- `server.c`: example server code, waits for messages indefinitely and replies
Both use `udp.c` as a simple UDP communication library.
The `Makefile` builds `client` and `server` executables. Type `make` to do this.
To run: type `server &` to run the server in the background; then type `client` to
run the client. You will likely then want to kill the server if you are done.
If you want to run these on different machines, you'll have to change the client
to send messages to the machine the server is running upon, instead of `localhost`.

28
dist-intro/client.c Normal file
View File

@@ -0,0 +1,28 @@
#include <stdio.h>
#include "udp.h"
#define BUFFER_SIZE (1000)
// client code
int main(int argc, char *argv[]) {
struct sockaddr_in addrSnd, addrRcv;
int sd = UDP_Open(20000);
int rc = UDP_FillSockAddr(&addrSnd, "localhost", 10000);
char message[BUFFER_SIZE];
sprintf(message, "hello world");
printf("client:: send message [%s]\n", message);
rc = UDP_Write(sd, &addrSnd, message, BUFFER_SIZE);
if (rc < 0) {
printf("client:: failed to send\n");
exit(1);
}
printf("client:: wait for reply...\n");
rc = UDP_Read(sd, &addrRcv, message, BUFFER_SIZE);
printf("client:: got reply [size:%d contents:(%s)\n", rc, message);
return 0;
}

28
dist-intro/server.c Normal file
View File

@@ -0,0 +1,28 @@
#include <stdio.h>
#include "udp.h"
#define BUFFER_SIZE (1000)
// server code
int main(int argc, char *argv[]) {
int sd = UDP_Open(10000);
assert(sd > -1);
while (1) {
struct sockaddr_in addr;
char message[BUFFER_SIZE];
printf("server:: waiting...\n");
int rc = UDP_Read(sd, &addr, message, BUFFER_SIZE);
printf("server:: read message [size:%d contents:(%s)]\n", rc, message);
if (rc > 0) {
char reply[BUFFER_SIZE];
sprintf(reply, "goodbye world");
rc = UDP_Write(sd, &addr, reply, BUFFER_SIZE);
printf("server:: reply\n");
}
}
return 0;
}

67
dist-intro/udp.c Normal file
View File

@@ -0,0 +1,67 @@
#include "udp.h"
// create a socket and bind it to a port on the current machine
// used to listen for incoming packets
int UDP_Open(int port) {
int fd;
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("socket");
return 0;
}
// set up the bind
struct sockaddr_in my_addr;
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(port);
my_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(fd, (struct sockaddr *) &my_addr, sizeof(my_addr)) == -1) {
perror("bind");
close(fd);
return -1;
}
return fd;
}
// fill sockaddr_in struct with proper goodies
int UDP_FillSockAddr(struct sockaddr_in *addr, char *hostname, int port) {
bzero(addr, sizeof(struct sockaddr_in));
if (hostname == NULL) {
return 0; // it's OK just to clear the address
}
addr->sin_family = AF_INET; // host byte order
addr->sin_port = htons(port); // short, network byte order
struct in_addr *in_addr;
struct hostent *host_entry;
if ((host_entry = gethostbyname(hostname)) == NULL) {
perror("gethostbyname");
return -1;
}
in_addr = (struct in_addr *) host_entry->h_addr;
addr->sin_addr = *in_addr;
return 0;
}
int UDP_Write(int fd, struct sockaddr_in *addr, char *buffer, int n) {
int addr_len = sizeof(struct sockaddr_in);
int rc = sendto(fd, buffer, n, 0, (struct sockaddr *) addr, addr_len);
return rc;
}
int UDP_Read(int fd, struct sockaddr_in *addr, char *buffer, int n) {
int len = sizeof(struct sockaddr_in);
int rc = recvfrom(fd, buffer, n, 0, (struct sockaddr *) addr, (socklen_t *) &len);
// assert(len == sizeof(struct sockaddr_in));
return rc;
}
int UDP_Close(int fd) {
return close(fd);
}

39
dist-intro/udp.h Normal file
View File

@@ -0,0 +1,39 @@
#ifndef __UDP_h__
#define __UDP_h__
//
// includes
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <netinet/tcp.h>
#include <netinet/in.h>
//
// prototypes
//
int UDP_Open(int port);
int UDP_Close(int fd);
int UDP_Read(int fd, struct sockaddr_in *addr, char *buffer, int n);
int UDP_Write(int fd, struct sockaddr_in *addr, char *buffer, int n);
int UDP_FillSockAddr(struct sockaddr_in *addr, char *hostName, int port);
#endif // __UDP_h__