aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsotech117 <michael_foiani@brown.edu>2023-09-14 16:14:15 -0400
committersotech117 <michael_foiani@brown.edu>2023-09-14 16:14:15 -0400
commit6eb71f25820d1ea1a050b4847338f2300734affd (patch)
treeb9a42e53bcbb1f67d93a291be85adfb6754ec11c
parentd9303149cb989e7af96b3964cf34018f295ba312 (diff)
good starting point, finished the guide
-rw-r--r--.vscode/c_cpp_properties.json19
-rw-r--r--Makefile13
-rwxr-xr-xclientbin0 -> 34200 bytes
-rw-r--r--client.c100
-rw-r--r--client.dSYM/Contents/Info.plist20
-rw-r--r--client.dSYM/Contents/Resources/DWARF/clientbin0 -> 11222 bytes
-rw-r--r--listener.c95
-rw-r--r--reference.c72
-rwxr-xr-xserverbin0 -> 34656 bytes
-rw-r--r--server.c144
-rw-r--r--server.dSYM/Contents/Info.plist20
-rw-r--r--server.dSYM/Contents/Resources/DWARF/serverbin0 -> 12990 bytes
-rw-r--r--talker.c67
13 files changed, 550 insertions, 0 deletions
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
new file mode 100644
index 0000000..9a0a2f5
--- /dev/null
+++ b/.vscode/c_cpp_properties.json
@@ -0,0 +1,19 @@
+{
+ "configurations": [
+ {
+ "name": "Mac",
+ "includePath": [
+ "${workspaceFolder}/**"
+ ],
+ "defines": [],
+ "macFrameworkPath": [
+ "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks"
+ ],
+ "compilerPath": "/usr/bin/clang",
+ "cStandard": "c17",
+ "cppStandard": "c++17",
+ "intelliSenseMode": "macos-clang-arm64"
+ }
+ ],
+ "version": 4
+} \ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..5e808ed
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,13 @@
+CC = gcc
+CFLAGS = -std=c99 -target x86_64-apple-darwin20 -g
+RM = rm -f
+
+default: all
+
+all: server client
+
+server: server.c
+ $(CC) $(CFLAGS) -o server server.c
+
+client: client.c
+ $(CC) $(CFLAGS) -o client client.c \ No newline at end of file
diff --git a/client b/client
new file mode 100755
index 0000000..2277b67
--- /dev/null
+++ b/client
Binary files differ
diff --git a/client.c b/client.c
new file mode 100644
index 0000000..591d030
--- /dev/null
+++ b/client.c
@@ -0,0 +1,100 @@
+/*
+** client.c -- a stream socket client demo
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+
+#define PORT "3490" // the port client will be connecting to
+
+#define MAXDATASIZE 100 // max number of bytes we can get at once
+
+// get sockaddr, IPv4 or IPv6:
+void *get_in_addr(struct sockaddr *sa)
+{
+ if (sa->sa_family == AF_INET) {
+ return &(((struct sockaddr_in*)sa)->sin_addr);
+ }
+
+ return &(((struct sockaddr_in6*)sa)->sin6_addr);
+}
+
+int main(int argc, char *argv[])
+{
+ int sockfd, numbytesrecv, numbytessent;
+ char buf[MAXDATASIZE];
+ struct addrinfo hints, *servinfo, *p;
+ int rv;
+ char s[INET6_ADDRSTRLEN];
+
+ if (argc != 3) {
+ fprintf(stderr,"usage: client hostname\n");
+ exit(1);
+ }
+
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_INET; // only IPv4
+ hints.ai_socktype = SOCK_STREAM;
+
+ if ((rv = getaddrinfo(argv[2], PORT, &hints, &servinfo)) != 0) {
+ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
+ return 1;
+ }
+
+ // loop through all the results and connect to the first we can
+ for(p = servinfo; p != NULL; p = p->ai_next) {
+ if ((sockfd = socket(p->ai_family, p->ai_socktype,
+ p->ai_protocol)) == -1) {
+ perror("client: socket");
+ continue;
+ }
+
+ if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
+ close(sockfd);
+ perror("client: connect");
+ continue;
+ }
+
+ break;
+ }
+
+ if (p == NULL) {
+ fprintf(stderr, "client: failed to connect\n");
+ return 2;
+ }
+
+ inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
+ s, sizeof s);
+ printf("client: connecting to %s\n", s);
+
+ freeaddrinfo(servinfo); // all done with this structure
+
+ if ((numbytesrecv = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
+ perror("recv");
+ exit(1);
+ }
+
+ buf[numbytesrecv] = '\0';
+
+ printf("client: received '%s'\n",buf);
+
+ if ((numbytessent = send(sockfd, "Welcome", 7, 0)) == -1) {
+ perror("send");
+ exit(1);
+ }
+
+ buf[numbytessent] = '\0';
+
+ close(sockfd);
+
+ return 0;
+} \ No newline at end of file
diff --git a/client.dSYM/Contents/Info.plist b/client.dSYM/Contents/Info.plist
new file mode 100644
index 0000000..d550748
--- /dev/null
+++ b/client.dSYM/Contents/Info.plist
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+ <dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.xcode.dsym.client</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>dSYM</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ </dict>
+</plist>
diff --git a/client.dSYM/Contents/Resources/DWARF/client b/client.dSYM/Contents/Resources/DWARF/client
new file mode 100644
index 0000000..4d642ff
--- /dev/null
+++ b/client.dSYM/Contents/Resources/DWARF/client
Binary files differ
diff --git a/listener.c b/listener.c
new file mode 100644
index 0000000..723cb1b
--- /dev/null
+++ b/listener.c
@@ -0,0 +1,95 @@
+/*
+** listener.c -- a datagram sockets "server" demo
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#define MYPORT "4950" // the port users will be connecting to
+
+#define MAXBUFLEN 100
+
+// get sockaddr, IPv4 or IPv6:
+void *get_in_addr(struct sockaddr *sa)
+{
+ if (sa->sa_family == AF_INET) {
+ return &(((struct sockaddr_in*)sa)->sin_addr);
+ }
+
+ return &(((struct sockaddr_in6*)sa)->sin6_addr);
+}
+
+int main(void)
+{
+ int sockfd;
+ struct addrinfo hints, *servinfo, *p;
+ int rv;
+ int numbytes;
+ struct sockaddr_storage their_addr;
+ char buf[MAXBUFLEN];
+ socklen_t addr_len;
+ char s[INET6_ADDRSTRLEN];
+
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_INET6; // set to AF_INET to use IPv4
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_PASSIVE; // use my IP
+
+ if ((rv = getaddrinfo(NULL, MYPORT, &hints, &servinfo)) != 0) {
+ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
+ return 1;
+ }
+
+ // loop through all the results and bind to the first we can
+ for(p = servinfo; p != NULL; p = p->ai_next) {
+ if ((sockfd = socket(p->ai_family, p->ai_socktype,
+ p->ai_protocol)) == -1) {
+ perror("listener: socket");
+ continue;
+ }
+
+ if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
+ close(sockfd);
+ perror("listener: bind");
+ continue;
+ }
+
+ break;
+ }
+
+ if (p == NULL) {
+ fprintf(stderr, "listener: failed to bind socket\n");
+ return 2;
+ }
+
+ freeaddrinfo(servinfo);
+
+ printf("listener: waiting to recvfrom...\n");
+
+ addr_len = sizeof their_addr;
+ if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0,
+ (struct sockaddr *)&their_addr, &addr_len)) == -1) {
+ perror("recvfrom");
+ exit(1);
+ }
+
+ printf("listener: got packet from %s\n",
+ inet_ntop(their_addr.ss_family,
+ get_in_addr((struct sockaddr *)&their_addr),
+ s, sizeof s));
+ printf("listener: packet is %d bytes long\n", numbytes);
+ buf[numbytes] = '\0';
+ printf("listener: packet contains \"%s\"\n", buf);
+
+ close(sockfd);
+
+ return 0;
+}
diff --git a/reference.c b/reference.c
new file mode 100644
index 0000000..1f5b74b
--- /dev/null
+++ b/reference.c
@@ -0,0 +1,72 @@
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+struct addrinfo {
+ int ai_flags; // AI_PASSIVE, AI_CANONNAME, etc.
+ int ai_family; // AF_INET, AF_INET6, AF_UNSPEC
+ int ai_socktype; // SOCK_STREAM, SOCK_DGRAM
+ int ai_protocol; // use 0 for "any"
+ size_t ai_addrlen; // size of ai_addr in bytes
+ struct sockaddr *ai_addr; // struct sockaddr_in or _in6
+ char *ai_canonname; // full canonical hostname
+
+ struct addrinfo *ai_next; // linked list, next node
+};
+
+struct sockaddr {
+ unsigned short sa_family; // address family, AF_xxx
+ char sa_data[14]; // 14 bytes of protocol address
+};
+
+struct sockaddr_in {
+ short int sin_family; // Address family, AF_INET
+ unsigned short int sin_port; // Port number
+ struct in_addr sin_addr; // Internet address
+ unsigned char sin_zero[8]; // Same size as struct sockaddr
+};
+
+// (IPv4 only--see struct in6_addr for IPv6)
+// Internet address (a structure for historical reasons)
+struct in_addr {
+ uint32_t s_addr; // that's a 32-bit int (4 bytes)
+};
+
+struct sockaddr_storage {
+ sa_family_t ss_family; // address family
+
+ // all this is padding, implementation specific, ignore it:
+ char __ss_pad1[_SS_PAD1SIZE];
+ int64_t __ss_align;
+ char __ss_pad2[_SS_PAD2SIZE];
+};
+
+int getaddrinfo(const char *node, // e.g. "www.example.com" or IP
+ const char *service, // e.g. "http" or port number
+ const struct addrinfo *hints,
+ struct addrinfo **res);
+
+
+// sockets!
+#include <sys/types.h>
+#include <sys/socket.h>
+
+int socket(int domain, int type, int protocol);
+
+int s;
+struct addrinfo hints, *res;
+
+// do the lookup
+// [pretend we already filled out the "hints" struct]
+getaddrinfo("www.example.com", "http", &hints, &res);
+
+// again, you should do error-checking on getaddrinfo(), and walk
+// the "res" linked list looking for valid entries instead of just
+// assuming the first one is good (like many of these examples do).
+// See the section on client/server for real examples.
+
+s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); \ No newline at end of file
diff --git a/server b/server
new file mode 100755
index 0000000..4f78e6c
--- /dev/null
+++ b/server
Binary files differ
diff --git a/server.c b/server.c
new file mode 100644
index 0000000..ea7d62c
--- /dev/null
+++ b/server.c
@@ -0,0 +1,144 @@
+/*
+** server.c -- a stream socket server demo
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+#define PORT "3490" // the port users will be connecting to
+
+#define BACKLOG 10 // how many pending connections queue will hold
+
+#define MAXDATASIZE 100 // max number of bytes we can get at once
+
+
+void sigchld_handler(int s)
+{
+ // waitpid() might overwrite errno, so we save and restore it:
+ int saved_errno = errno;
+
+ while(waitpid(-1, NULL, WNOHANG) > 0);
+
+ errno = saved_errno;
+}
+
+
+// get sockaddr, IPv4 or IPv6:
+void *get_in_addr(struct sockaddr *sa)
+{
+ if (sa->sa_family == AF_INET) {
+ return &(((struct sockaddr_in*)sa)->sin_addr);
+ }
+
+ return &(((struct sockaddr_in6*)sa)->sin6_addr);
+}
+
+int main(void)
+{
+ int sockfd, new_fd, numbytes; // listen on sock_fd, new connection on new_fd
+ char buf[MAXDATASIZE];
+ struct addrinfo hints, *servinfo, *p;
+ struct sockaddr_storage their_addr; // connector's address information
+ socklen_t sin_size;
+ struct sigaction sa;
+ int yes=1;
+ char s[INET6_ADDRSTRLEN];
+ int rv;
+
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_INET; // only IPv4
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE; // use my IP
+
+ if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
+ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
+ return 1;
+ }
+
+ // loop through all the results and bind to the first we can
+ for(p = servinfo; p != NULL; p = p->ai_next) {
+ if ((sockfd = socket(p->ai_family, p->ai_socktype,
+ p->ai_protocol)) == -1) {
+ perror("server: socket");
+ continue;
+ }
+
+ if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
+ sizeof(int)) == -1) {
+ perror("setsockopt");
+ exit(1);
+ }
+
+ if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
+ close(sockfd);
+ perror("server: bind");
+ continue;
+ }
+
+ break;
+ }
+
+ freeaddrinfo(servinfo); // all done with this structure
+
+ if (p == NULL) {
+ fprintf(stderr, "server: failed to bind\n");
+ exit(1);
+ }
+
+ if (listen(sockfd, BACKLOG) == -1) {
+ perror("listen");
+ exit(1);
+ }
+
+ sa.sa_handler = sigchld_handler; // reap all dead processes
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ if (sigaction(SIGCHLD, &sa, NULL) == -1) {
+ perror("sigaction");
+ exit(1);
+ }
+
+ printf("server: waiting for connections...\n");
+
+ while(1) { // main accept() loop
+ sin_size = sizeof their_addr;
+ new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
+ if (new_fd == -1) {
+ perror("accept");
+ continue;
+ }
+
+ inet_ntop(their_addr.ss_family,
+ get_in_addr((struct sockaddr *)&their_addr),
+ s, sizeof s);
+ printf("server: got connection from %s\n", s);
+
+ if (!fork()) { // this is the child process
+
+ close(sockfd); // child doesn't need the listener
+ if (send(new_fd, "Hello, world!", 13, 0) == -1)
+ perror("send");
+ // close(new_fd);
+ if ((numbytes = recv(new_fd, buf, MAXDATASIZE-1, 0)) == -1) {
+ perror("recv");
+ exit(1);
+ }
+ buf[numbytes] = '\0';
+ printf("server: received '%s'\n",buf);
+ exit(0);
+ }
+ close(new_fd); // parent doesn't need this
+ }
+
+ return 0;
+} \ No newline at end of file
diff --git a/server.dSYM/Contents/Info.plist b/server.dSYM/Contents/Info.plist
new file mode 100644
index 0000000..d2b6274
--- /dev/null
+++ b/server.dSYM/Contents/Info.plist
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+ <dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.xcode.dsym.server</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>dSYM</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ </dict>
+</plist>
diff --git a/server.dSYM/Contents/Resources/DWARF/server b/server.dSYM/Contents/Resources/DWARF/server
new file mode 100644
index 0000000..22ad6d7
--- /dev/null
+++ b/server.dSYM/Contents/Resources/DWARF/server
Binary files differ
diff --git a/talker.c b/talker.c
new file mode 100644
index 0000000..bb801e5
--- /dev/null
+++ b/talker.c
@@ -0,0 +1,67 @@
+/*
+** talker.c -- a datagram "client" demo
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#define SERVERPORT "4950" // the port users will be connecting to
+
+int main(int argc, char *argv[])
+{
+ int sockfd;
+ struct addrinfo hints, *servinfo, *p;
+ int rv;
+ int numbytes;
+
+ if (argc != 3) {
+ fprintf(stderr,"usage: talker hostname message\n");
+ exit(1);
+ }
+
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_INET6; // set to AF_INET to use IPv4
+ hints.ai_socktype = SOCK_DGRAM;
+
+ if ((rv = getaddrinfo(argv[1], SERVERPORT, &hints, &servinfo)) != 0) {
+ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
+ return 1;
+ }
+
+ // loop through all the results and make a socket
+ for(p = servinfo; p != NULL; p = p->ai_next) {
+ if ((sockfd = socket(p->ai_family, p->ai_socktype,
+ p->ai_protocol)) == -1) {
+ perror("talker: socket");
+ continue;
+ }
+
+ break;
+ }
+
+ if (p == NULL) {
+ fprintf(stderr, "talker: failed to create socket\n");
+ return 2;
+ }
+
+ if ((numbytes = sendto(sockfd, argv[2], strlen(argv[2]), 0,
+ p->ai_addr, p->ai_addrlen)) == -1) {
+ perror("talker: sendto");
+ exit(1);
+ }
+
+ freeaddrinfo(servinfo);
+
+ printf("talker: sent %d bytes to %s\n", numbytes, argv[1]);
+ close(sockfd);
+
+ return 0;
+} \ No newline at end of file