├── framing ├── DieWithMessage.c ├── HandleMessageClient.c ├── Makefile ├── MessageServer.c ├── Practical.h └── README.txt └── sockets ├── DieWithMessage.c ├── HandleTCPClient.c ├── Makefile ├── Practical.h ├── README.txt ├── TCPClient.c ├── TCPEchoServer.c └── showip.c /framing/DieWithMessage.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void DieWithUserMessage(const char *msg, const char *detail) { 5 | fputs(msg, stderr); 6 | fputs(": ", stderr); 7 | fputs(detail, stderr); 8 | fputc('\n', stderr); 9 | exit(1); 10 | } 11 | 12 | void DieWithSystemMessage(const char *msg) { 13 | perror(msg); 14 | exit(1); 15 | } 16 | -------------------------------------------------------------------------------- /framing/HandleMessageClient.c: -------------------------------------------------------------------------------- 1 | #include /* for printf() and fprintf() */ 2 | #include 3 | #include /* for recv() and send() */ 4 | #include /* for close() */ 5 | #include 6 | #include 7 | #include 8 | 9 | #include "Practical.h" 10 | 11 | #define RCVBUFSIZE 32 /* Size of receive buffer */ 12 | 13 | using namespace std; 14 | 15 | void HandleMessageClient(int clntSocket) 16 | { 17 | string msgbuffer; 18 | char recvbuf[RCVBUFSIZE]; 19 | 20 | while(true) { 21 | memset(recvbuf, 0, RCVBUFSIZE); // clear out the receive buffer 22 | int numRecvBytes = recv(clntSocket, recvbuf, RCVBUFSIZE, 0); 23 | 24 | if (numRecvBytes < 0) { 25 | if (errno == EAGAIN || errno == EWOULDBLOCK) { 26 | fprintf(stderr, "Client timed out, closing connection\n"); 27 | close(clntSocket); 28 | return; 29 | } 30 | 31 | perror("recv"); 32 | close(clntSocket); 33 | return; 34 | } 35 | 36 | if (numRecvBytes == 0) { 37 | fprintf(stderr, "remote end closed the connection\n"); 38 | close(clntSocket); 39 | return; 40 | } 41 | 42 | msgbuffer = msgbuffer + string(recvbuf, numRecvBytes); 43 | 44 | cout << "Message buffer is: " << msgbuffer.c_str() << endl; 45 | 46 | size_t delimoffset = msgbuffer.find("=="); 47 | while (delimoffset != string::npos) { 48 | string msg = msgbuffer.substr(0, delimoffset); 49 | msgbuffer = msgbuffer.substr(delimoffset+2, string::npos); 50 | cout << "Message received: " << msg << endl; 51 | delimoffset = msgbuffer.find("=="); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /framing/Makefile: -------------------------------------------------------------------------------- 1 | CC=g++ 2 | CFLAGS=-ggdb -std=c++11 -Wall -pedantic -Wno-sign-compare 3 | 4 | all: server 5 | 6 | server: MessageServer.c DieWithMessage.c HandleMessageClient.c 7 | $(CC) $(CFLAGS) -o server MessageServer.c DieWithMessage.c HandleMessageClient.c 8 | 9 | clean: 10 | rm -rf server 11 | -------------------------------------------------------------------------------- /framing/MessageServer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "Practical.h" 12 | 13 | void HandleMessageClient(int clntSocket); /* TCP client handling function */ 14 | 15 | #define MAXPENDING 5 /* Maximum outstanding connection requests */ 16 | #define RCVBUFSIZE 32 /* Size of receive buffer */ 17 | 18 | int main(int argc, char *argv[]) 19 | { 20 | int servSock; /* Socket descriptor for server */ 21 | int clntSock; /* Socket descriptor for client */ 22 | struct addrinfo hints, *servinfo, *p; 23 | int rv; 24 | struct sockaddr_in msgClntAddr; /* Client address */ 25 | unsigned int clntLen; /* Length of client address data structure */ 26 | 27 | if (argc != 2) /* Test for correct number of arguments */ 28 | { 29 | fprintf(stderr, "Usage: %s \n", argv[0]); 30 | exit(1); 31 | } 32 | 33 | memset(&hints, 0, sizeof hints); 34 | hints.ai_family = AF_UNSPEC; // Prefer IPv6, but allow IPv4 35 | hints.ai_socktype = SOCK_STREAM; // use TCP 36 | hints.ai_flags = AI_PASSIVE; // we're going to be a server 37 | 38 | if ((rv = getaddrinfo(NULL, argv[1], &hints, &servinfo)) != 0) { 39 | fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); 40 | exit(1); 41 | } 42 | 43 | for (p = servinfo; p != NULL; p = p->ai_next) { 44 | if ((servSock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) 45 | { 46 | perror("socket"); 47 | continue; 48 | } 49 | 50 | if (bind(servSock, p->ai_addr, p->ai_addrlen) == -1) { 51 | close(servSock); 52 | perror("bind"); 53 | continue; 54 | } 55 | 56 | break; 57 | } 58 | 59 | if (p == NULL) { 60 | fprintf(stderr, "failed to bind to a socket\n"); 61 | exit(2); 62 | } 63 | 64 | freeaddrinfo(servinfo); 65 | 66 | /* Mark the socket so it will listen for incoming connections */ 67 | if (listen(servSock, MAXPENDING) < 0) { 68 | DieWithSystemMessage("listen() failed"); 69 | } 70 | 71 | int optval = 1; 72 | if (setsockopt(servSock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) != 0) { 73 | DieWithSystemMessage("setsockopt()"); 74 | } 75 | 76 | for (;;) /* Run forever */ 77 | { 78 | /* Set the size of the in-out parameter */ 79 | clntLen = sizeof(msgClntAddr); 80 | 81 | /* Wait for a client to connect */ 82 | if ((clntSock = accept(servSock, (struct sockaddr *) &msgClntAddr, 83 | &clntLen)) < 0) 84 | DieWithSystemMessage("accept() failed"); 85 | 86 | /* clntSock is connected to a client! */ 87 | 88 | printf("Handling client %s\n", inet_ntoa(msgClntAddr.sin_addr)); 89 | 90 | struct timeval timeout; 91 | timeout.tv_sec = 5; 92 | timeout.tv_usec = 0; 93 | 94 | if (setsockopt(clntSock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0) { 95 | DieWithSystemMessage("setsockopt()"); 96 | } 97 | 98 | HandleMessageClient(clntSock); 99 | } 100 | /* NOT REACHED */ 101 | } 102 | -------------------------------------------------------------------------------- /framing/Practical.h: -------------------------------------------------------------------------------- 1 | #ifndef PRACTICAL_H_ 2 | #define PRACTICAL_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | // Handle error with user msg 9 | void DieWithUserMessage(const char *msg, const char *detail); 10 | // Handle error with sys msg 11 | void DieWithSystemMessage(const char *msg); 12 | // Print socket address 13 | void PrintSocketAddress(const struct sockaddr *address, FILE *stream); 14 | // Test socket address equality 15 | bool SockAddrsEqual(const struct sockaddr *addr1, const struct sockaddr *addr2); 16 | // Create, bind, and listen a new TCP server socket 17 | int SetupTCPServerSocket(const char *service); 18 | // Accept a new TCP connection on a server socket 19 | int AcceptTCPConnection(int servSock); 20 | // Handle new TCP client 21 | void HandleTCPClient(int clntSocket); 22 | // Create and connect a new TCP client socket 23 | int SetupTCPClientSocket(const char *server, const char *service); 24 | 25 | enum sizeConstants { 26 | MAXSTRINGLENGTH = 128, 27 | BUFSIZE = 512, 28 | }; 29 | 30 | #endif // PRACTICAL_H_ 31 | -------------------------------------------------------------------------------- /framing/README.txt: -------------------------------------------------------------------------------- 1 | This code adapted from The Donahoo and Calvert examples 2 | http://cs.baylor.edu/~donahoo/practical/CSockets/textcode.html 3 | -------------------------------------------------------------------------------- /sockets/DieWithMessage.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void DieWithUserMessage(const char *msg, const char *detail) { 5 | fputs(msg, stderr); 6 | fputs(": ", stderr); 7 | fputs(detail, stderr); 8 | fputc('\n', stderr); 9 | exit(1); 10 | } 11 | 12 | void DieWithSystemMessage(const char *msg) { 13 | perror(msg); 14 | exit(1); 15 | } 16 | -------------------------------------------------------------------------------- /sockets/HandleTCPClient.c: -------------------------------------------------------------------------------- 1 | #include /* for printf() and fprintf() */ 2 | #include /* for recv() and send() */ 3 | #include /* for close() */ 4 | 5 | #include "Practical.h" 6 | 7 | #define RCVBUFSIZE 32 /* Size of receive buffer */ 8 | 9 | void HandleTCPClient(int clntSocket) 10 | { 11 | char echoBuffer[RCVBUFSIZE]; /* Buffer for echo string */ 12 | int recvMsgSize; /* Size of received message */ 13 | 14 | /* Receive message from client */ 15 | if ((recvMsgSize = recv(clntSocket, echoBuffer, RCVBUFSIZE, 0)) < 0) 16 | DieWithSystemMessage("recv() failed"); 17 | 18 | /* Send received string and receive again until end of transmission */ 19 | while (recvMsgSize > 0) /* zero indicates end of transmission */ 20 | { 21 | /* Echo message back to client */ 22 | if (send(clntSocket, echoBuffer, recvMsgSize, 0) != recvMsgSize) 23 | DieWithSystemMessage("send() failed"); 24 | 25 | /* See if there is more data to receive */ 26 | if ((recvMsgSize = recv(clntSocket, echoBuffer, RCVBUFSIZE, 0)) < 0) 27 | DieWithSystemMessage("recv() failed"); 28 | } 29 | 30 | close(clntSocket); /* Close client socket */ 31 | } 32 | -------------------------------------------------------------------------------- /sockets/Makefile: -------------------------------------------------------------------------------- 1 | CC=g++ 2 | CFLAGS=-ggdb -std=c++11 -Wall -pedantic -Wno-sign-compare 3 | 4 | all: client showip server 5 | 6 | showip: showip.c 7 | $(CC) $(CFLAGS) -o showip showip.c 8 | 9 | client: TCPClient.c DieWithMessage.c 10 | $(CC) $(CFLAGS) -o client TCPClient.c DieWithMessage.c 11 | 12 | server: HandleTCPClient.c TCPEchoServer.c DieWithMessage.c 13 | $(CC) $(CFLAGS) -o server HandleTCPClient.c TCPEchoServer.c DieWithMessage.c 14 | 15 | clean: 16 | rm -rf client server showip 17 | -------------------------------------------------------------------------------- /sockets/Practical.h: -------------------------------------------------------------------------------- 1 | #ifndef PRACTICAL_H_ 2 | #define PRACTICAL_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | // Handle error with user msg 9 | void DieWithUserMessage(const char *msg, const char *detail); 10 | // Handle error with sys msg 11 | void DieWithSystemMessage(const char *msg); 12 | // Print socket address 13 | void PrintSocketAddress(const struct sockaddr *address, FILE *stream); 14 | // Test socket address equality 15 | bool SockAddrsEqual(const struct sockaddr *addr1, const struct sockaddr *addr2); 16 | // Create, bind, and listen a new TCP server socket 17 | int SetupTCPServerSocket(const char *service); 18 | // Accept a new TCP connection on a server socket 19 | int AcceptTCPConnection(int servSock); 20 | // Handle new TCP client 21 | void HandleTCPClient(int clntSocket); 22 | // Create and connect a new TCP client socket 23 | int SetupTCPClientSocket(const char *server, const char *service); 24 | 25 | enum sizeConstants { 26 | MAXSTRINGLENGTH = 128, 27 | BUFSIZE = 512, 28 | }; 29 | 30 | #endif // PRACTICAL_H_ 31 | -------------------------------------------------------------------------------- /sockets/README.txt: -------------------------------------------------------------------------------- 1 | This code adapted from The Donahoo and Calvert examples 2 | http://cs.baylor.edu/~donahoo/practical/CSockets/textcode.html 3 | -------------------------------------------------------------------------------- /sockets/TCPClient.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "Practical.h" 16 | 17 | using namespace std; 18 | 19 | /* Given a sockaddr struct, return it as a string (from D&C book) */ 20 | char * get_ip_str(const struct sockaddr *sa, char *s, size_t maxlen); 21 | 22 | /* a.out host port */ 23 | int main(int argc, char *argv[]) { 24 | if (argc != 3) { 25 | DieWithUserMessage("Parameter(s)", "host port"); 26 | } 27 | 28 | const char * host = argv[1]; 29 | const char * port = argv[2]; 30 | 31 | struct addrinfo hints, *servinfo, *p; 32 | int rv, sock; 33 | 34 | fprintf(stderr, "Connecting to %s:%s\n", host, port); 35 | 36 | memset(&hints, 0, sizeof(hints)); 37 | hints.ai_family = AF_UNSPEC; // either IPv6 or IPV4 OK 38 | hints.ai_socktype = SOCK_STREAM; // use tcp 39 | 40 | if ((rv = getaddrinfo(host, port, &hints, &servinfo)) != 0) { 41 | DieWithUserMessage("getaddrinfo", gai_strerror(rv)); 42 | } 43 | 44 | for (p = servinfo; p != NULL; p = p->ai_next) { 45 | if ((sock = socket(p->ai_family, p->ai_socktype, 46 | p->ai_protocol)) == -1) { 47 | DieWithUserMessage("socket", "Couldn't connect to address"); 48 | } 49 | 50 | if (connect(sock, p->ai_addr, p->ai_addrlen) == -1) { 51 | DieWithUserMessage("socket", "can't connect"); 52 | } 53 | 54 | break; 55 | } 56 | 57 | if (p == NULL) { 58 | DieWithUserMessage("socket", "Didn't find an address to connect to"); 59 | } 60 | freeaddrinfo(servinfo); 61 | 62 | char addrbuf[128]; 63 | get_ip_str(p->ai_addr, addrbuf, 128); 64 | fprintf(stderr, "Connected to %s!\n", addrbuf); 65 | 66 | const char * message = "Hi from CSE 224!\n"; 67 | int ret = send(sock, message, strlen(message), 0); 68 | if (ret != strlen(message)) { 69 | DieWithSystemMessage("send() failed"); 70 | } 71 | 72 | // Receive the response 73 | ssize_t numBytes; 74 | do { 75 | char buffer[BUFSIZE]; // I/O buffer 76 | numBytes = recv(sock, buffer, BUFSIZE - 1, 0); 77 | if (numBytes < 0) 78 | DieWithSystemMessage("recv() failed"); 79 | else if (numBytes == 0) 80 | break; 81 | buffer[numBytes] = '\0'; // Terminate the string! 82 | fputs(buffer, stdout); // Print the echo buffer 83 | } while (numBytes > 0); 84 | 85 | fputc('\n', stdout); // Print a final linefeed 86 | 87 | close(sock); 88 | fprintf(stderr, "Closed the socket!\n"); 89 | 90 | exit(0); 91 | } 92 | 93 | char * get_ip_str(const struct sockaddr *sa, char *s, size_t maxlen) 94 | { 95 | switch(sa->sa_family) { 96 | case AF_INET: 97 | inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr), 98 | s, maxlen); 99 | break; 100 | 101 | case AF_INET6: 102 | inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr), 103 | s, maxlen); 104 | break; 105 | 106 | default: 107 | strncpy(s, "Unknown AF", maxlen); 108 | return NULL; 109 | } 110 | 111 | return s; 112 | } 113 | -------------------------------------------------------------------------------- /sockets/TCPEchoServer.c: -------------------------------------------------------------------------------- 1 | #include /* for printf() and fprintf() */ 2 | #include /* for socket(), bind(), and connect() */ 3 | #include /* for sockaddr_in and inet_ntoa() */ 4 | #include /* for atoi() and exit() */ 5 | #include /* for memset() */ 6 | #include /* for close() */ 7 | 8 | #include "Practical.h" 9 | 10 | #define MAXPENDING 5 /* Maximum outstanding connection requests */ 11 | 12 | void HandleTCPClient(int clntSocket); /* TCP client handling function */ 13 | 14 | int main(int argc, char *argv[]) 15 | { 16 | int servSock; /* Socket descriptor for server */ 17 | int clntSock; /* Socket descriptor for client */ 18 | struct sockaddr_in echoServAddr; /* Local address */ 19 | struct sockaddr_in echoClntAddr; /* Client address */ 20 | unsigned short echoServPort; /* Server port */ 21 | unsigned int clntLen; /* Length of client address data structure */ 22 | 23 | if (argc != 2) /* Test for correct number of arguments */ 24 | { 25 | fprintf(stderr, "Usage: %s \n", argv[0]); 26 | exit(1); 27 | } 28 | 29 | echoServPort = atoi(argv[1]); /* First arg: local port */ 30 | 31 | /* Create socket for incoming connections */ 32 | if ((servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) 33 | DieWithSystemMessage("socket() failed"); 34 | 35 | /* Construct local address structure */ 36 | memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */ 37 | echoServAddr.sin_family = AF_INET; /* Internet address family */ 38 | echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */ 39 | echoServAddr.sin_port = htons(echoServPort); /* Local port */ 40 | 41 | /* Bind to the local address */ 42 | if (bind(servSock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0) 43 | DieWithSystemMessage("bind() failed"); 44 | 45 | /* Mark the socket so it will listen for incoming connections */ 46 | if (listen(servSock, MAXPENDING) < 0) 47 | DieWithSystemMessage("listen() failed"); 48 | 49 | for (;;) /* Run forever */ 50 | { 51 | /* Set the size of the in-out parameter */ 52 | clntLen = sizeof(echoClntAddr); 53 | 54 | /* Wait for a client to connect */ 55 | if ((clntSock = accept(servSock, (struct sockaddr *) &echoClntAddr, 56 | &clntLen)) < 0) 57 | DieWithSystemMessage("accept() failed"); 58 | 59 | /* clntSock is connected to a client! */ 60 | 61 | printf("Handling client %s\n", inet_ntoa(echoClntAddr.sin_addr)); 62 | 63 | HandleTCPClient(clntSock); 64 | } 65 | /* NOT REACHED */ 66 | } 67 | -------------------------------------------------------------------------------- /sockets/showip.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** showip.c -- show IP addresses for a host given on the command line 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | struct addrinfo hints, *res, *p; 16 | int status; 17 | char ipstr[INET6_ADDRSTRLEN]; 18 | 19 | if (argc != 2) { 20 | fprintf(stderr,"usage: showip hostname\n"); 21 | return 1; 22 | } 23 | 24 | memset(&hints, 0, sizeof hints); 25 | hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version 26 | hints.ai_socktype = SOCK_STREAM; 27 | 28 | if ((status = getaddrinfo(argv[1], NULL, &hints, &res)) != 0) { 29 | fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); 30 | return 2; 31 | } 32 | 33 | printf("IP addresses for %s:\n\n", argv[1]); 34 | 35 | for(p = res;p != NULL; p = p->ai_next) { 36 | void *addr; 37 | const char *ipver; 38 | 39 | // get the pointer to the address itself, 40 | // different fields in IPv4 and IPv6: 41 | if (p->ai_family == AF_INET) { // IPv4 42 | struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; 43 | addr = &(ipv4->sin_addr); 44 | ipver = "IPv4"; 45 | } else { // IPv6 46 | struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; 47 | addr = &(ipv6->sin6_addr); 48 | ipver = "IPv6"; 49 | } 50 | 51 | // convert the IP to a string and print it: 52 | inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr); 53 | printf(" %s: %s\n", ipver, ipstr); 54 | } 55 | 56 | freeaddrinfo(res); // free the linked list 57 | 58 | return 0; 59 | } 60 | --------------------------------------------------------------------------------