Skip to content

Instantly share code, notes, and snippets.

@jsuwo
Last active August 29, 2015 14:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jsuwo/78a43a72337574b56e3d to your computer and use it in GitHub Desktop.
Save jsuwo/78a43a72337574b56e3d to your computer and use it in GitHub Desktop.
Code samples from Computer Networks I Lab Manual, Chapter 4 - TCP Socket Programming
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
struct addrinfo* get_sockaddr(const char* hostname, const char* port)
{
struct addrinfo hints;
struct addrinfo* results;
int retval;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET; // Return socket addresses for the server's IPv4 addresses
hints.ai_socktype = SOCK_STREAM; // Return TCP socket addresses
retval = getaddrinfo(NULL, port, &hints, &results);
if (retval != 0)
{
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(retval));
exit(EXIT_FAILURE);
}
return results;
}
int open_connection(struct addrinfo* addr_list)
{
struct addrinfo* addr;
int sockfd;
// Iterate through each addrinfo in the list; stop when we successfully
// connect 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;
// Stop iterating if we're able to connect to the server
if (connect(sockfd, addr->ai_addr, addr->ai_addrlen) != -1)
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 connect to any
if (addr == NULL)
{
perror("Unable to connect");
exit(EXIT_FAILURE);
}
else
{
return sockfd;
}
}
int main(int argc, char** argv)
{
// Connect to the server
struct addrinfo* results = get_sockaddr("localhost", "5000");
int sockfd = open_connection(results);
// Close the connection
close(sockfd);
exit(EXIT_SUCCESS);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
struct addrinfo* get_sockaddr(const char* hostname, const char* port)
{
struct addrinfo hints;
struct addrinfo* results;
int retval;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET; // Return socket addresses for the server's IPv4 addresses
hints.ai_socktype = SOCK_STREAM; // Return TCP socket addresses
retval = getaddrinfo(NULL, port, &hints, &results);
if (retval != 0)
{
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(retval));
exit(EXIT_FAILURE);
}
return results;
}
int open_connection(struct addrinfo* addr_list)
{
struct addrinfo* addr;
int sockfd;
// Iterate through each addrinfo in the list; stop when we successfully
// connect 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;
// Stop iterating if we're able to connect to the server
if (connect(sockfd, addr->ai_addr, addr->ai_addrlen) != -1)
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 connect to any
if (addr == NULL)
{
perror("Unable to connect");
exit(EXIT_FAILURE);
}
else
{
return sockfd;
}
}
int main(int argc, char** argv)
{
int bytes_read; // Number of bytes read from the server
char* msg = "hello world\r\n"; // Message to send
char buffer[strlen(msg) + 1]; // Buffer to store received message, leaving
// space for the NULL terminator
// Connect to the server
struct addrinfo* results = get_sockaddr("localhost", "5000");
int sockfd = open_connection(results);
// Send the message
if (send(sockfd, msg, strlen(msg), 0) == -1)
{
perror("Unable to send");
exit(EXIT_FAILURE);
}
// Read the echo reply
bytes_read = recv(sockfd, buffer, sizeof(buffer), 0);
if (bytes_read == -1)
{
perror("Unable to read");
exit(EXIT_FAILURE);
}
// Add the terminating NULL character to the end and print it
buffer[bytes_read] = '\0';
printf("Data received: %s", buffer);
// Close the connection
close(sockfd);
exit(EXIT_SUCCESS);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
int main(int argc, char** argv)
{
struct addrinfo hints; // Hints passed to getaddrinfo
struct addrinfo* results; // Linked list of results populated by getaddrinfo
struct addrinfo* res; // Pointer to a result in the linked list
int retval; // Value returned by getaddrinfo
char ip_address[INET_ADDRSTRLEN]; // Buffer to store human-readable IP address
// Initialize hints and request IPv4 addresses
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
// Attempt to resolve the IP address
retval = getaddrinfo(argv[1], NULL, &hints, &results);
// If the function was unsuccessful
if (retval != 0)
{
// Convert the return value to a human-readable error, print it, and exit
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(retval));
exit(retval);
}
// Iterate through each result in the results linked list
for (res = results; res != NULL; res = res->ai_next)
{
// Cast the result's address to a Internet socket address
struct sockaddr_in* ipv4 = (struct sockaddr_in*)res->ai_addr;
// Convert it from its packed, binary form to a human readable string
inet_ntop(res->ai_family, &ipv4->sin_addr, ip_address, sizeof(ip_address));
// Display the IP address
printf("%s\n", ip_address);
}
// Free the memory allocated to the linked list
freeaddrinfo(results);
exit(EXIT_SUCCESS);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
int main(int argc, char** argv)
{
struct addrinfo hints; // Hints passed to getaddrinfo
struct addrinfo* results; // Linked list of results populated by getaddrinfo
struct addrinfo* res; // Pointer to a result in the linked list
int retval; // Value returned by getaddrinfo
char ip_address[INET_ADDRSTRLEN]; // Buffer to store human-readable IP address
// Initialize hints and request IPv4 addresses
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
// Return only results suitable for creating TCP sockets
hints.ai_socktype = SOCK_STREAM;
// Attempt to resolve the IP address
retval = getaddrinfo(argv[1], NULL, &hints, &results);
// If the function was unsuccessful
if (retval != 0)
{
// Convert the return value to a human-readable error, print it, and exit
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(retval));
exit(retval);
}
// Iterate through each result in the results linked list
for (res = results; res != NULL; res = res->ai_next)
{
// Cast the result's address to a Internet socket address
struct sockaddr_in* ipv4 = (struct sockaddr_in*)res->ai_addr;
// Convert it from its packed, binary form to a human readable string
inet_ntop(res->ai_family, &ipv4->sin_addr, ip_address, sizeof(ip_address));
// Display the IP address
printf("%s\n", ip_address);
}
// Free the memory allocated to the linked list
freeaddrinfo(results);
exit(EXIT_SUCCESS);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#define BACKLOG 25
struct addrinfo* get_server_sockaddr(const char* port)
{
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_STREAM; // Return TCP socket addresses
hints.ai_flags = AI_PASSIVE; // Socket addresses should be listening sockets
retval = getaddrinfo(NULL, port, &hints, &results);
if (retval != 0)
{
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(retval));
exit(EXIT_FAILURE);
}
return results;
}
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 wait_for_connection(int sockfd)
{
struct sockaddr_in client_addr; // Remote IP that is connecting to us
int addr_len = sizeof(struct sockaddr_in); // Length of the remote IP structure
char ip_address[INET_ADDRSTRLEN]; // Buffer to store human-friendly IP address
int connectionfd; // Socket file descriptor for the new connection
// Wait for a new connection
connectionfd = accept(sockfd, (struct sockaddr*)&client_addr, &addr_len);
// Make sure the connection was established successfully
if (connectionfd == -1)
{
perror("Unable to accept connection");
exit(EXIT_FAILURE);
}
// Convert the connecting IP to a human-friendly form and print it
inet_ntop(client_addr.sin_family, &client_addr.sin_addr, ip_address, sizeof(ip_address));
printf("Connection accepted from %s\n", ip_address);
// Return the socket file descriptor for the new connection
return connectionfd;
}
int main(int argc, char** argv)
{
// We want to listen on port 5000
struct addrinfo* results = get_server_sockaddr("5000");
// Create a listening socket
int sockfd = bind_socket(results);
// Start listening on the socket
if (listen(sockfd, BACKLOG) == -1)
{
perror("Unable to listen on socket");
exit(EXIT_FAILURE);
}
// Wait for a connection
int connectionfd = wait_for_connection(sockfd);
exit(EXIT_SUCCESS);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#define BACKLOG 25
struct addrinfo* get_server_sockaddr(const char* port)
{
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_STREAM; // Return TCP socket addresses
hints.ai_flags = AI_PASSIVE; // Socket addresses should be listening sockets
retval = getaddrinfo(NULL, port, &hints, &results);
if (retval != 0)
{
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(retval));
exit(EXIT_FAILURE);
}
return results;
}
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 wait_for_connection(int sockfd)
{
struct sockaddr_in client_addr; // Remote IP that is connecting to us
int addr_len = sizeof(struct sockaddr_in); // Length of the remote IP structure
char ip_address[INET_ADDRSTRLEN]; // Buffer to store human-friendly IP address
int connectionfd; // Socket file descriptor for the new connection
// Wait for a new connection
connectionfd = accept(sockfd, (struct sockaddr*)&client_addr, &addr_len);
// Make sure the connection was established successfully
if (connectionfd == -1)
{
perror("Unable to accept connection");
exit(EXIT_FAILURE);
}
// Convert the connecting IP to a human-friendly form and print it
inet_ntop(client_addr.sin_family, &client_addr.sin_addr, ip_address, sizeof(ip_address));
printf("Connection accepted from %s\n", ip_address);
// Return the socket file descriptor for the new connection
return connectionfd;
}
void handle_connection(int connectionfd)
{
char buffer[4096];
int bytes_read;
// Read up to 4096 bytes from the client
bytes_read = recv(connectionfd, buffer, sizeof(buffer), 0);
// If the data was read successfully
if (bytes_read > 0)
{
// Add a terminating NULL character and print the message received
buffer[bytes_read] = '\0';
printf("Message received: %s", buffer);
// Echo the data back to the client
if (send(connectionfd, buffer, bytes_read, 0) == -1)
{
perror("Unable to send to socket");
exit(EXIT_FAILURE);
}
}
else if (bytes_read == -1)
{
// Otherwise, if the read failed,
perror("Unable to read from socket");
exit(EXIT_FAILURE);
}
// Close the connection
close(connectionfd);
}
int main(int argc, char** argv)
{
// We want to listen on port 5000
struct addrinfo* results = get_server_sockaddr("5000");
// Create a listening socket
int sockfd = bind_socket(results);
// Start listening on the socket
if (listen(sockfd, BACKLOG) == -1)
{
perror("Unable to listen on socket");
exit(EXIT_FAILURE);
}
// Wait for a connection and handle it
int connectionfd = wait_for_connection(sockfd);
handle_connection(connectionfd);
exit(EXIT_SUCCESS);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#define BACKLOG 25
struct addrinfo* get_server_sockaddr(const char* port)
{
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_STREAM; // Return TCP socket addresses
hints.ai_flags = AI_PASSIVE; // Socket addresses should be listening sockets
retval = getaddrinfo(NULL, port, &hints, &results);
if (retval != 0)
{
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(retval));
exit(EXIT_FAILURE);
}
return results;
}
int bind_socket(struct addrinfo* addr_list)
{
struct addrinfo* addr;
int sockfd;
char yes = '1';
// 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;
// Allow the port to be re-used if currently in the TIME_WAIT state
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
{
perror("Unable to set socket option");
exit(EXIT_FAILURE);
}
// 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 wait_for_connection(int sockfd)
{
struct sockaddr_in client_addr; // Remote IP that is connecting to us
int addr_len = sizeof(struct sockaddr_in); // Length of the remote IP structure
char ip_address[INET_ADDRSTRLEN]; // Buffer to store human-friendly IP address
int connectionfd; // Socket file descriptor for the new connection
// Wait for a new connection
connectionfd = accept(sockfd, (struct sockaddr*)&client_addr, &addr_len);
// Make sure the connection was established successfully
if (connectionfd == -1)
{
perror("Unable to accept connection");
exit(EXIT_FAILURE);
}
// Convert the connecting IP to a human-friendly form and print it
inet_ntop(client_addr.sin_family, &client_addr.sin_addr, ip_address, sizeof(ip_address));
printf("Connection accepted from %s\n", ip_address);
// Return the socket file descriptor for the new connection
return connectionfd;
}
void handle_connection(int connectionfd)
{
char buffer[4096];
int bytes_read;
// Read up to 4096 bytes from the client
bytes_read = recv(connectionfd, buffer, sizeof(buffer), 0);
// If the data was read successfully
if (bytes_read > 0)
{
// Add a terminating NULL character and print the message received
buffer[bytes_read] = '\0';
printf("Message received: %s", buffer);
// Echo the data back to the client
if (send(connectionfd, buffer, bytes_read, 0) == -1)
{
perror("Unable to send to socket");
exit(EXIT_FAILURE);
}
}
else if (bytes_read == -1)
{
// Otherwise, if the read failed,
perror("Unable to read from socket");
exit(EXIT_FAILURE);
}
// Close the connection
close(connectionfd);
}
int main(int argc, char** argv)
{
// We want to listen on port 5000
struct addrinfo* results = get_server_sockaddr("5000");
// Create a listening socket
int sockfd = bind_socket(results);
// Start listening on the socket
if (listen(sockfd, BACKLOG) == -1)
{
perror("Unable to listen on socket");
exit(EXIT_FAILURE);
}
while (1)
{
// Wait for a connection and handle it
int connectionfd = wait_for_connection(sockfd);
handle_connection(connectionfd);
}
exit(EXIT_SUCCESS);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment