Last active
November 9, 2015 04:32
-
-
Save jsuwo/dc02f8332df2eaae5b55 to your computer and use it in GitHub Desktop.
Code samples from Computer Networks I Lab Manual, Chapter 5 - UDP Socket Programming
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include "udp_client.h" | |
#include "udp_sockets.h" | |
int main() | |
{ | |
host server; // Server address | |
message* msg; // Message to send/receive | |
// Create a socket for communication with the server | |
int sockfd = create_client_socket("localhost", "5000", &server); | |
// Create a message, and initialize its contents | |
msg = create_message(); | |
msg->length = strlen("hello"); | |
memcpy(msg->buffer, "hello", msg->length); | |
// Send the message to the server, and free its memory | |
int retval = send_message(sockfd, msg, &server); | |
free(msg); | |
// If we couldn't send the message, exit the program | |
if (retval == -1) | |
{ | |
close(sockfd); | |
perror("Unable to send to socket"); | |
exit(EXIT_FAILURE); | |
} | |
// Read the server's reply | |
msg = receive_message(sockfd, &server); | |
if (msg != NULL) | |
{ | |
// Add NULL terminator and print reply | |
msg->buffer[msg->length] = '\0'; | |
printf("Reply from server %s: %s\n", server.friendly_ip, msg->buffer); | |
// Free the memory allocated to the message | |
free(msg); | |
} | |
// Close the socket | |
close(sockfd); | |
exit(EXIT_SUCCESS); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <arpa/inet.h> | |
#include <netdb.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <sys/socket.h> | |
#include <sys/types.h> | |
#include <unistd.h> | |
#include "udp_sockets.h" | |
#include "udp_server.h" | |
int main() | |
{ | |
int bytes_read; // Number of bytes read | |
char buffer[65535]; // Buffer to store incoming message | |
char ip_address[INET_ADDRSTRLEN]; // Buffer to store human-readable source IP address | |
struct sockaddr_in addr; // Source address and port | |
socklen_t addr_len = sizeof(struct sockaddr_in); // Length of the addr structure | |
// Create a socket to listen on port 5000 | |
int sockfd = create_server_socket("5000"); | |
// Read the next message into buffer, storing the source address in addr | |
bytes_read = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&addr, &addr_len); | |
// Convert the source address to a human-readable IP address | |
inet_ntop(addr.sin_family, &addr.sin_addr, ip_address, sizeof(ip_address)); | |
if (bytes_read > 0) | |
{ | |
// Add NULL terminator | |
buffer[bytes_read] = '\0'; | |
printf("Message received from %s: %s\n", ip_address, buffer); | |
} | |
// Close the socket | |
close(sockfd); | |
exit(EXIT_SUCCESS); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include "udp_sockets.h" | |
#include "udp_server.h" | |
int main() | |
{ | |
message* msg; // Message received | |
host source; // Source of the message received | |
// Create a socket to listen on port 5000 | |
int sockfd = create_server_socket("5000"); | |
// Read the next message | |
msg = receive_message(sockfd, &source); | |
if (msg != NULL) | |
{ | |
// Add NULL terminator | |
msg->buffer[msg->length] = '\0'; | |
printf("Message received from %s: %s\n", source.friendly_ip, msg->buffer); | |
} | |
// Free the memory allocated to the message | |
free(msg); | |
// Close the socket | |
close(sockfd); | |
exit(EXIT_SUCCESS); | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include "udp_sockets.h" | |
#include "udp_server.h" | |
int main() | |
{ | |
message* msg; // Message received | |
host source; // Source of the message received | |
// Create a socket to listen on port 5000 | |
int sockfd = create_server_socket("5000"); | |
// Read the next message | |
msg = receive_message(sockfd, &source); | |
if (msg != NULL) | |
{ | |
// Add NULL terminator | |
msg->buffer[msg->length] = '\0'; | |
printf("Message received from %s: %s\n", source.friendly_ip, msg->buffer); | |
// Echo the message back to the client | |
if (sendto(sockfd, msg->buffer, msg->length, 0, | |
(struct sockaddr*)&source.addr, source.addr_len) == -1) | |
{ | |
free(msg); | |
perror("Unable to send to socket"); | |
exit(EXIT_FAILURE); | |
} | |
} | |
// Free the memory allocated to the message | |
free(msg); | |
// Close the socket | |
close(sockfd); | |
exit(EXIT_SUCCESS); | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CC=gcc | |
CFLAGS=-Wall -Werror -std=gnu11 -g -c | |
LFLAGS=-Wall -Werror -g | |
all: fig5-3 fig5-4 fig5-5 server client | |
fig5-3: fig5-3.o udp_sockets.o udp_server.o | |
$(CC) $(LFLAGS) -o $@ $^ | |
fig5-4: fig5-4.o udp_sockets.o udp_server.o | |
$(CC) $(LFLAGS) -o $@ $^ | |
fig5-5: fig5-5.o udp_sockets.o udp_server.o | |
$(CC) $(LFLAGS) -o $@ $^ | |
server: server.o udp_sockets.o udp_server.o | |
$(CC) $(LFLAGS) -o $@ $^ | |
client: client.o udp_sockets.o udp_client.o | |
$(CC) $(LFLAGS) -o $@ $^ | |
fig5-3.o: fig5-3.c udp_server.h udp_sockets.h | |
$(CC) $(CFLAGS) -o $@ $< | |
fig5-4.o: fig5-4.c udp_server.h udp_sockets.h | |
$(CC) $(CFLAGS) -o $@ $< | |
fig5-5.o: fig5-5.c udp_server.h udp_sockets.h | |
$(CC) $(CFLAGS) -o $@ $< | |
server.o: server.c udp_server.h udp_sockets.h | |
$(CC) $(CFLAGS) -o $@ $< | |
client.o: client.c udp_client.h udp_sockets.h | |
$(CC) $(CFLAGS) -o $@ $< | |
udp_sockets.o: udp_sockets.c udp_sockets.h | |
$(CC) $(CFLAGS) -o $@ $< | |
udp_server.o: udp_server.c udp_server.h udp_sockets.h | |
$(CC) $(CFLAGS) -o $@ $< | |
udp_client.o: udp_client.c udp_client.h udp_sockets.h | |
$(CC) $(CFLAGS) -o $@ $< | |
clean: | |
rm -f *.o fig5-3 fig5-4 fig5-5 server client | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include "udp_sockets.h" | |
#include "udp_server.h" | |
int main() | |
{ | |
message* msg; // Message received | |
host source; // Source of the message received | |
// Create a socket to listen on port 5000 | |
int sockfd = create_server_socket("5000"); | |
// Read the next message | |
msg = receive_message(sockfd, &source); | |
if (msg != NULL) | |
{ | |
// Add NULL terminator | |
msg->buffer[msg->length] = '\0'; | |
printf("Message received from %s: %s\n", source.friendly_ip, msg->buffer); | |
// Echo the message back to the client | |
if (send_message(sockfd, msg, &source) == -1) | |
{ | |
free(msg); | |
perror("Unable to send to socket"); | |
exit(EXIT_FAILURE); | |
} | |
} | |
// Free the memory allocated to the message | |
free(msg); | |
// Close the socket | |
close(sockfd); | |
exit(EXIT_SUCCESS); | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include "udp_client.h" | |
int create_client_socket(char* hostname, char* port, host* server) | |
{ | |
int sockfd; | |
struct addrinfo* addr; | |
struct addrinfo* results = get_udp_sockaddr(hostname, port, 0); | |
// Iterate through each addrinfo in the list; | |
// stop when we successfully create a socket | |
for (addr = results; addr != NULL; addr = addr->ai_next) | |
{ | |
// Open a socket | |
sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); | |
// Try the next address if we couldn't open a socket | |
if (sockfd == -1) | |
continue; | |
// Copy server address and length to the out parameter 'server' | |
memcpy(&server->addr, addr->ai_addr, addr->ai_addrlen); | |
memcpy(&server->addr_len, &addr->ai_addrlen, sizeof(addr->ai_addrlen)); | |
// We've successfully created a socket; stop iterating | |
break; | |
} | |
// Free the memory allocated to the addrinfo list | |
freeaddrinfo(results); | |
// If we tried every addrinfo and failed to create a socket | |
if (addr == NULL) | |
{ | |
perror("Unable to create socket"); | |
exit(EXIT_FAILURE); | |
} | |
else | |
{ | |
// Otherwise, return the socket descriptor | |
return sockfd; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "udp_sockets.h" | |
#ifndef UDP_CLIENT_H | |
#define UDP_CLIENT_H | |
int create_client_socket(char* hostname, char* port, host* server); | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <netdb.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <sys/socket.h> | |
#include <unistd.h> | |
#include "udp_server.h" | |
#include "udp_sockets.h" | |
int bind_socket(struct addrinfo* addr_list) | |
{ | |
struct addrinfo* addr; | |
int sockfd; | |
// Iterate through each addrinfo in the list; stop when we successfully bind | |
// to one | |
for (addr = addr_list; addr != NULL; addr = addr->ai_next) | |
{ | |
// Open a socket | |
sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); | |
// Try the next address if we couldn't open a socket | |
if (sockfd == -1) | |
continue; | |
// Try to bind the socket to the address/port | |
if (bind(sockfd, addr->ai_addr, addr->ai_addrlen) == -1) | |
{ | |
// If binding fails, close the socket, and try the next address | |
close(sockfd); | |
continue; | |
} | |
else | |
{ | |
// Otherwise, we've bound the address/port to the socket, so stop | |
// processing | |
break; | |
} | |
} | |
// Free the memory allocated to the addrinfo list | |
freeaddrinfo(addr_list); | |
// If addr is NULL, we tried every addrinfo and weren't able to bind to any | |
if (addr == NULL) | |
{ | |
perror("Unable to bind"); | |
exit(EXIT_FAILURE); | |
} | |
else | |
{ | |
// Otherwise, return the socket descriptor | |
return sockfd; | |
} | |
} | |
int create_server_socket(char* port) | |
{ | |
struct addrinfo* results = get_udp_sockaddr(NULL, port, AI_PASSIVE); | |
int sockfd = bind_socket(results); | |
return sockfd; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <netdb.h> | |
#ifndef UDP_SERVER_H | |
#define UDP_SERVER_H | |
int bind_socket(struct addrinfo* addr_list); | |
int create_server_socket(char* port); | |
#endif | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <arpa/inet.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include "udp_sockets.h" | |
struct addrinfo* get_udp_sockaddr(const char* node, const char* port, int flags) | |
{ | |
struct addrinfo hints; | |
struct addrinfo* results; | |
int retval; | |
memset(&hints, 0, sizeof(struct addrinfo)); | |
hints.ai_family = AF_INET; // Return socket addresses for our local IPv4 addresses | |
hints.ai_socktype = SOCK_DGRAM; // Return UDP socket addresses | |
hints.ai_flags = flags; // Socket addresses should be listening sockets | |
retval = getaddrinfo(node, port, &hints, &results); | |
if (retval != 0) | |
{ | |
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(retval)); | |
exit(EXIT_FAILURE); | |
} | |
return results; | |
} | |
message* create_message() | |
{ | |
return (message*)malloc(sizeof(message)); | |
} | |
message* receive_message(int sockfd, host* source) | |
{ | |
message* msg = create_message(); | |
// Length of the remote IP structure | |
source->addr_len = sizeof(source->addr); | |
// Read message, storing its contents in msg->buffer, and | |
// the source address in source->addr | |
msg->length = recvfrom(sockfd, msg->buffer, sizeof(msg->buffer), 0, | |
(struct sockaddr*)&source->addr, | |
&source->addr_len); | |
// If a message was read | |
if (msg->length > 0) | |
{ | |
// Convert the source address to a human-readable form, | |
// storing it in source->friendly_ip | |
inet_ntop(source->addr.sin_family, &source->addr.sin_addr, | |
source->friendly_ip, sizeof(source->friendly_ip)); | |
// Return the message received | |
return msg; | |
} | |
else | |
{ | |
// Otherwise, free the allocated memory and return NULL | |
free(msg); | |
return NULL; | |
} | |
} | |
int send_message(int sockfd, message* msg, host* dest) | |
{ | |
return sendto(sockfd, msg->buffer, msg->length, 0, | |
(struct sockaddr*)&dest->addr, dest->addr_len); | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <netdb.h> | |
#ifndef UDP_SOCKETS_H | |
#define UDP_SOCKETS_H | |
#define UDP_MSS 65535 | |
typedef struct | |
{ | |
int length; | |
uint8_t buffer[UDP_MSS]; | |
} message; | |
typedef struct | |
{ | |
struct sockaddr_in addr; | |
socklen_t addr_len; | |
char friendly_ip[INET_ADDRSTRLEN]; | |
} host; | |
struct addrinfo* get_udp_sockaddr(const char* node, const char* port, int flags); | |
message* create_message(); | |
message* receive_message(int sockfd, host* source); | |
int send_message(int sockfd, message* msg, host* dest); | |
#endif | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment