### C: accept() Example for Handling Incoming Connections Source: https://beej.us/guide/bgnet/html/index This C code example demonstrates how to use the accept() function after setting up a listening socket. It includes necessary setup with getaddrinfo(), socket(), bind(), and listen(), and shows how to retrieve the new socket descriptor for communication. ```c struct sockaddr_storage their_addr; socklen_t addr_size; struct addrinfo hints, *res; int sockfd, new_fd; // first, load up address structs with getaddrinfo(): memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; // fill in my IP for me getaddrinfo(NULL, MYPORT, &hints, &res); // make a socket, bind it, and listen on it: sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); bind(sockfd, res->ai_addr, res->ai_addrlen); listen(sockfd, BACKLOG); // now accept an incoming connection: addr_size = sizeof their_addr; new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &addr_size); // ready to communicate on socket descriptor new_fd! ``` -------------------------------- ### Server Setup with getaddrinfo() Source: https://beej.us/guide/bgnet/html/index Example of using getaddrinfo() for a server application. It configures hints to listen on any interface (NULL node) for TCP connections on a specific port. Error handling using gai_strerror() is demonstrated. ```c int status; struct addrinfo hints; struct addrinfo *servinfo; // will point to the results memset(&hints, 0, sizeof hints); // make sure the struct is empty hints.ai_family = AF_UNSPEC; // don't care IPv4 or IPv6 hints.ai_socktype = SOCK_STREAM; // TCP stream sockets hints.ai_flags = AI_PASSIVE; // fill in my IP for me if ((status = getaddrinfo(NULL, "3490", &hints, &servinfo)) != 0) { fprintf(stderr, "gai error: %s\n", gai_strerror(status)); exit(1); } // servinfo now points to a linked list of 1 or more // struct addrinfos // ... do everything until you don't need servinfo anymore .... freeaddrinfo(servinfo); // free the linked-list ``` -------------------------------- ### C Example: Connecting to a remote host using connect() and getaddrinfo() Source: https://beej.us/guide/bgnet/html/index This example demonstrates how to use `getaddrinfo()` to resolve a hostname and port, create a socket, and then establish a connection to the remote host using `connect()`. It assumes the necessary headers and structures are defined. ```c struct addrinfo hints, *res; int sockfd; // first, load up address structs with getaddrinfo(): memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; getaddrinfo("www.example.com", "3490", &hints, &res); // make a socket: sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); // connect! connect(sockfd, res->ai_addr, res->ai_addrlen); ``` -------------------------------- ### C Network Server Setup and `accept()` Usage Source: https://beej.us/guide/bgnet/html/index A C code fragment demonstrating the setup of a network server, including socket creation, binding, listening, and using `accept()` to handle an incoming connection. It utilizes `getaddrinfo` for address resolution and establishes a new socket descriptor for communication. ```c #include #include #include #include #define MYPORT "3490" // the port users will be connecting to #define BACKLOG 10 // how many pending connections queue holds int main(void) { struct sockaddr_storage their_addr; socklen_t addr_size; struct addrinfo hints, *res; int sockfd, new_fd; // !! don't forget your error checking for these calls !! // first, load up address structs with getaddrinfo(): memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; // fill in my IP for me getaddrinfo(NULL, MYPORT, &hints, &res); // make a socket, bind it, and listen on it: sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); bind(sockfd, res->ai_addr, res->ai_addrlen); listen(sockfd, BACKLOG); // now accept an incoming connection: addr_size = sizeof their_addr; new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &addr_size); // ready to communicate on socket descriptor new_fd! . . . } ``` -------------------------------- ### Socket Creation and Select Example (C) Source: https://beej.us/guide/bgnet/html/index Demonstrates how to create a socket and use the select() system call to monitor socket activity. Includes error handling for interrupted system calls. ```C s = socket(PF_INET, SOCK_STREAM, 0); if (s == -1) { perror("socket"); // or use strerror() } tryagain: if (select(n, &readfds, NULL, NULL) == -1) { // an error has occurred!! // if we were only interrupted, just restart the select() call: if (errno == EINTR) goto tryagain; // AAAA! goto!!! // otherwise it's a more serious error: perror("select"); exit(1); } ``` -------------------------------- ### Create a Socket Descriptor in C Source: https://beej.us/guide/bgnet/html/index Provides an example of using the `socket()` system call to create a new socket descriptor. It demonstrates how to obtain parameters for `domain`, `type`, and `protocol` using `getaddrinfo()` for IPv4/IPv6 and TCP/UDP socket types. ```c struct addrinfo hints, *res; int sockfd; // first, load up address structs with getaddrinfo(): memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; // AF_INET, AF_INET6, or AF_UNSPEC hints.ai_socktype = SOCK_STREAM; // SOCK_STREAM or SOCK_DGRAM getaddrinfo("www.example.com", "3490", &hints, &res); // make a socket using the information gleaned from getaddrinfo(): sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); ``` -------------------------------- ### C: Network Listener Socket Setup Source: https://beej.us/guide/bgnet/html/index This function sets up a listening TCP socket on the specified port. It uses getaddrinfo to resolve address information and then creates, binds, and listens on the socket. It includes error handling and options for reusing the address. ```c #include #include #include #include #include #include #include #include #include #include #define PORT "9034" // Port we're listening on /* * Return a listening socket. */ int get_listener_socket(void) { int listener; // Listening socket descriptor int yes=1; // For setsockopt() SO_REUSEADDR, below int rv; struct addrinfo hints, *ai, *p; // Get us a socket and bind it memset(&hints, 0, sizeof hints); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; if ((rv = getaddrinfo(NULL, PORT, &hints, &ai)) != 0) { fprintf(stderr, "pollserver: %s\n", gai_strerror(rv)); exit(1); } for(p = ai; p != NULL; p = p->ai_next) { listener = socket(p->ai_family, p->ai_socktype, p->ai_protocol); if (listener < 0) { continue; } // Lose the pesky "address already in use" error message setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); if (bind(listener, p->ai_addr, p->ai_addrlen) < 0) { close(listener); continue; } break; } // If we got here, it means we didn't get bound if (p == NULL) { return -1; } freeaddrinfo(ai); // All done with this // Listen if (listen(listener, 10) == -1) { return -1; } return listener; } ``` -------------------------------- ### Configure Socket Options with setsockopt and getsockopt (C) Source: https://beej.us/guide/bgnet/html/index Demonstrates how to set and get socket options using setsockopt and getsockopt in C. It covers options like SO_REUSEADDR for port reuse and SO_BINDTODEVICE for binding to a specific network interface. Note that some options might be system-dependent. ```c int optval; int optlen; char *optval2; // set SO_REUSEADDR on a socket to true (1): optval = 1; setsockopt(s1, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval); // bind a socket to a device name (might not work on all systems): optval2 = "eth1"; // 4 bytes long, so 4, below: setsockopt(s2, SOL_SOCKET, SO_BINDTODEVICE, optval2, 4); // see if the SO_BROADCAST flag is set: getsockopt(s3, SOL_SOCKET, SO_BROADCAST, &optval, &optlen); if (optval != 0) { print("SO_BROADCAST enabled on s3!\n"); } ``` -------------------------------- ### C Example: Binding an IPv4 Socket Source: https://beej.us/guide/bgnet/html/index Demonstrates how to create and bind a socket to an IPv4 address. It initializes a sockaddr_in structure with the address family, port, and IP address, then uses the socket() and bind() functions. The port is converted to network byte order using htons. ```c // IPv4: struct sockaddr_in ip4addr; int s; ip4addr.sin_family = AF_INET; ip4addr.sin_port = htons(3490); inet_pton(AF_INET, "10.0.0.1", &ip4addr.sin_addr); s = socket(PF_INET, SOCK_STREAM, 0); bind(s, (struct sockaddr*)&ip4addr, sizeof ip4addr); ``` -------------------------------- ### C Example: Binding an IPv6 Socket Source: https://beej.us/guide/bgnet/html/index Illustrates the process of creating and binding a socket to an IPv6 address. It involves setting up a sockaddr_in6 structure with the address family, port, and IPv6 address, followed by the use of socket() and bind() system calls. The port is converted to network byte order using htons. ```c // IPv6: struct sockaddr_in6 ip6addr; int s; ip6addr.sin6_family = AF_INET6; ip6addr.sin6_port = htons(4950); inet_pton(AF_INET6, "2001:db8:8714:3a90::12", &ip6addr.sin6_addr); s = socket(PF_INET6, SOCK_STREAM, 0); bind(s, (struct sockaddr*)&ip6addr, sizeof ip6addr); ``` -------------------------------- ### C: setsockopt() and getsockopt() Synopsis Source: https://beej.us/guide/bgnet/html/index This C code provides the synopsis for the setsockopt() and getsockopt() system calls. These functions are used to get and set various options on sockets, controlling network behavior and socket properties. ```c #include #include int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen); int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen); ``` -------------------------------- ### C: Example Usage of sendall() Function Source: https://beej.us/guide/bgnet/html/index This C code snippet demonstrates how to call the sendall() function to transmit data. It initializes a buffer with a string, calculates its length, and then calls sendall(). It includes error handling to report if the transmission was incomplete due to an error and indicates how many bytes were actually sent. ```c char buf[10] = "Beej!"; int len; len = strlen(buf); if (sendall(s, buf, &len) == -1) { perror("sendall"); printf("We only sent %d bytes because of the error!\n", len); } ``` -------------------------------- ### C Example: Waiting for Standard Input with select() Source: https://beej.us/guide/bgnet/html/index This C code snippet demonstrates the practical application of the `select()` function. It sets up a timeout of 2.5 seconds and monitors standard input. If a key press (followed by RETURN on a line-buffered terminal) occurs within the timeout period, it prints a confirmation; otherwise, it indicates a timeout. ```c /* ** select.c -- a select() demo */ #include #include #include #include #define STDIN 0 // file descriptor for standard input int main(void) { struct timeval tv; fd_set readfds; tv.tv_sec = 2; tv.tv_usec = 500000; FD_ZERO(&readfds); FD_SET(STDIN, &readfds); // don't care about writefds and exceptfds: select(STDIN+1, &readfds, NULL, NULL, &tv); if (FD_ISSET(STDIN, &readfds)) printf("A key was pressed!\n"); else printf("Timed out.\n"); return 0; } ``` -------------------------------- ### Send Data Over TCP and UDP Sockets in C Source: https://beej.us/guide/bgnet/html/index Demonstrates how to send data using the `send()` function for TCP stream sockets and `sendto()` for UDP datagram sockets. It includes examples of sending integers and strings, with and without the `MSG_OOB` flag for out-of-band data. ```c int spatula_count = 3490; char *secret_message = "The Cheese is in The Toaster"; int stream_socket, dgram_socket; struct sockaddr_in dest; int temp; // first with TCP stream sockets: // assume sockets are made and connected //stream_socket = socket(... //connect(stream_socket, ... // convert to network byte order temp = htonl(spatula_count); // send data normally: send(stream_socket, &temp, sizeof temp, 0); // send secret message out of band: send(stream_socket, secret_message, strlen(secret_message)+1, MSG_OOB); // now with UDP datagram sockets: //getaddrinfo(... //dest = ... // assume "dest" holds the address of the destination //dgram_socket = socket(... // send secret message normally: sendto(dgram_socket, secret_message, strlen(secret_message)+1, 0, (struct sockaddr*)&dest, sizeof dest); ``` -------------------------------- ### C poll() Example: Monitoring Standard Input Source: https://beej.us/guide/bgnet/html/index This C code demonstrates how to use the `poll()` system call to monitor standard input (file descriptor 0) for readability. It sets a 2.5-second timeout and checks the return value and `revents` to determine if data is ready or if the poll timed out. ```c #include #include int main(void) { struct pollfd pfds[1]; // More if you want to monitor more pfds[0].fd = 0; // Standard input pfds[0].events = POLLIN; // Tell me when ready to read // If you needed to monitor other things, as well: //pfds[1].fd = some_socket; // Some socket descriptor //pfds[1].events = POLLIN; // Tell me when ready to read printf("Hit RETURN or wait 2.5 seconds for timeout\n"); int num_events = poll(pfds, 1, 2500); // 2.5 second timeout if (num_events == 0) { printf("Poll timed out!\n"); } else { int pollin_happened = pfds[0].revents & POLLIN; if (pollin_happened) { printf("File descriptor %d is ready to read\n", pfds[0].fd); } else { printf("Unexpected event occurred: %d\n", pfds[0].revents); } } return 0; } ``` -------------------------------- ### Send Data Using send() and sendto() (C) Source: https://beej.us/guide/bgnet/html/index Provides C code examples for sending data over sockets using send() and sendto(). send() is typically used for connected TCP sockets, while sendto() is for unconnected UDP sockets, requiring destination address specification. Common flags like MSG_OOB, MSG_DONTROUTE, MSG_DONTWAIT, and MSG_NOSIGNAL are also illustrated. ```c #include #include // Example for send() - assumes a connected socket 's' // ssize_t send(int s, const void *buf, size_t len, int flags); // Example usage: // char message[] = "Hello, server!"; // send(s, message, strlen(message), 0); // Example for sendto() - assumes an unconnected socket 's' // ssize_t sendto(int s, const void *buf, size_t len, // int flags, const struct sockaddr *to, socklen_t tolen); // Example usage: // struct sockaddr_in server_addr; // // ... initialize server_addr with destination IP and port ... // char datagram[] = "This is a UDP packet"; // sendto(s, datagram, strlen(datagram), 0, (struct sockaddr *)&server_addr, sizeof(server_addr)); // Example with flags (conceptual): // send(s, data, length, MSG_DONTROUTE | MSG_NOSIGNAL); ``` -------------------------------- ### Secure Command Execution on Server (C) Source: https://beej.us/guide/bgnet/html/index This C code snippet demonstrates a basic security check for commands received by a server. It uses strncmp to verify if a received command string starts with 'foobar' before executing it via system(). This is a rudimentary measure against arbitrary command execution, highlighting the need for more robust sanitization. ```c if (!strncmp(str, "foobar", 6)) { sprintf(sysstr, "%s > /tmp/server.out", str); system(sysstr); } ``` -------------------------------- ### Initializing Winsock Library (WSAStartup) (C) Source: https://beej.us/guide/bgnet/html/index Before using any Winsock functions, you must initialize the Winsock library by calling WSAStartup(). This function takes the desired Winsock version and returns version information. Error handling is essential. ```c #include { WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { fprintf(stderr, "WSAStartup failed.\n"); exit(1); } if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { fprintf(stderr,"Version 2.2 of Winsock not available.\n"); WSACleanup(); exit(2); } } ``` -------------------------------- ### Receive Data from TCP Stream Socket using recv() in C Source: https://beej.us/guide/bgnet/html/index Demonstrates receiving data from a connected TCP stream socket using the `recv()` function. It shows the setup for creating and connecting a socket, followed by calling `recv()` to read data into a buffer. Assumes necessary headers and prior socket setup. ```c #include #include #include #include #include #include #include // stream sockets and recv() struct addrinfo hints, *res; int sockfd; char buf[512]; int byte_count; // get host info, make socket, and connect it memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever hints.ai_socktype = SOCK_STREAM; getaddrinfo("www.example.com", "3490", &hints, &res); sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); connect(sockfd, res->ai_addr, res->ai_addrlen); // all right! now that we're connected, we can receive some data! byte_count = recv(sockfd, buf, sizeof buf, 0); printf("recv()'d %d bytes of data in buf\n", byte_count); close(sockfd); freeaddrinfo(res); ``` -------------------------------- ### gethostname() - Get Local Hostname Source: https://beej.us/guide/bgnet/html/index The gethostname() function retrieves the name of the computer on which the program is running. ```APIDOC ## GET /hostname ### Description Retrieves the name of the computer on which the program is running. ### Method GET ### Endpoint `/hostname` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```json { "hostname": null, "size": 256 } ``` ### Response #### Success Response (200) - **hostname** (char *) - A pointer to an array of chars that will contain the hostname upon the function's return. #### Response Example ```json { "hostname": "my-local-machine" } ``` ``` -------------------------------- ### Client Connection Preparation with getaddrinfo() Source: https://beej.us/guide/bgnet/html/index Demonstrates using getaddrinfo() for a client application. It prepares hints to connect to a specific host and port using TCP sockets. The results are stored in servinfo for subsequent connection attempts. ```c int status; struct addrinfo hints; struct addrinfo *servinfo; // will point to the results memset(&hints, 0, sizeof hints); // make sure the struct is empty hints.ai_family = AF_UNSPEC; // don't care IPv4 or IPv6 hints.ai_socktype = SOCK_STREAM; // TCP stream sockets // get ready to connect status = getaddrinfo("www.example.net", "3490", &hints, &servinfo); // servinfo now points to a linked list of 1 or more // struct addrinfos // etc. ``` -------------------------------- ### getpeername() - Get Remote Peer Address Source: https://beej.us/guide/bgnet/html/index The getpeername() function retrieves the address of the connected peer on a stream socket. ```APIDOC ## GET /peername ### Description Retrieves the address of the connected peer on a stream socket. ### Method GET ### Endpoint `/peername` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```json { "sockfd": 1, "addr": null, "addrlen": null } ``` ### Response #### Success Response (200) - **addr** (struct sockaddr) - A pointer to a struct sockaddr that will hold the information about the other side of the connection. - **addrlen** (int *) - A pointer to an int, initialized to sizeof *addr or sizeof(struct sockaddr), which will contain the size of the address structure upon return. #### Response Example ```json { "addr": { "sa_family": 2, "sa_data": "\x1f\x90\x00\x50\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, "addrlen": 16 } ``` ``` -------------------------------- ### getaddrinfo, freeaddrinfo, gai_strerror Source: https://beej.us/guide/bgnet/html/index These functions are used to get information about a host name and/or service and load up a struct sockaddr with the result. ```APIDOC ## GETADDRINFO, FREEADDRINFO, GAI_STRERROR ### Description Get information about a host name and/or service and load up a `struct sockaddr` with the result. ### Synopsis ```c #include #include #include int getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res); void freeaddrinfo(struct addrinfo *ai); const char *gai_strerror(int ecode); struct addrinfo { int ai_flags; // AI_PASSIVE, AI_CANONNAME, ... int ai_family; // AF_xxx int ai_socktype; // SOCK_xxx int ai_protocol; // 0 (auto) or IPPROTO_TCP, IPPROTO_UDP socklen_t ai_addrlen; // length of ai_addr char *ai_canonname; // canonical name for nodename struct sockaddr *ai_addr; // binary address struct addrinfo *ai_next; // next structure in linked list }; ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```c // connect to www.example.com port 80 (http) struct addrinfo hints, *res; int sockfd; // first, load up address structs with getaddrinfo(): memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever hints.ai_socktype = SOCK_STREAM; // we could put "80" instead on "http" on the next line: getaddrinfo("www.example.com", "http", &hints, &res); // make a socket: sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); // connect it to the address and port we passed in to getaddrinfo(): connect(sockfd, res->ai_addr, res->ai_addrlen); ``` ### Response #### Success Response (200) None #### Response Example None ### See Also `socket()`, `bind()` ``` -------------------------------- ### getsockopt() / setsockopt() - Socket Options Source: https://beej.us/guide/bgnet/html/index These functions are used to get and set various options for a socket. They allow fine-grained control over socket behavior, such as buffer sizes, keep-alive settings, and more. ```APIDOC ## getsockopt() / setsockopt() ### Description Get and set various options for a socket. ### Synopsis ```c #include #include int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen); int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen); ``` ### Parameters #### `getsockopt` / `setsockopt` - **s** (int) - The socket descriptor. - **level** (int) - The protocol level at which the option applies (e.g., `SOL_SOCKET`). - **optname** (int) - The name of the socket option to retrieve or set (e.g., `SO_REUSEADDR`). - **optval** (void *) - A pointer to a buffer where the option value is stored or from which it is read. - **optlen** (socklen_t *) - For `getsockopt`, this is a value-result argument, the size of the buffer pointed to by `optval`. For `setsockopt`, it specifies the size of the option value pointed to by `optval`. ``` -------------------------------- ### Get Hostname Source: https://beej.us/guide/bgnet/html/index Retrieves the system's hostname and stores it in a provided buffer. The function ensures the hostname is NUL-terminated if space permits. It returns 0 on success and -1 on error. ```c #include #include char hostname[128]; gethostname(hostname, sizeof hostname); printf("My hostname: %s\n", hostname); ``` -------------------------------- ### IPv6 Any Address Initialization Source: https://beej.us/guide/bgnet/html/index Shows how to initialize a `struct in6_addr` with the IPv6 'any' address using the `IN6ADDR_ANY_INIT` macro. This is a convenient way to set the default IPv6 address. ```c struct in6_addr ia6 = IN6ADDR_ANY_INIT; ``` -------------------------------- ### Main Server Loop with select() in C Source: https://beej.us/guide/bgnet/html/index The main function initializes the server, sets up listening sockets, and enters a loop to monitor client activity using the `select()` system call. It manages file descriptor sets (`master` and `read_fds`) to track active connections and efficiently handle I/O events, including new connections and data reception. The `select()` call blocks until one or more file descriptors are ready. ```c /* * Main */ int main(void) { fd_set master; // master file descriptor list fd_set read_fds; // temp file descriptor list for select() int fdmax; // maximum file descriptor number int listener; // listening socket descriptor FD_ZERO(&master); // clear the master and temp sets FD_ZERO(&read_fds); listener = get_listener_socket(); // add the listener to the master set FD_SET(listener, &master); // keep track of the biggest file descriptor fdmax = listener; // so far, it's this one // main loop for(;;) { read_fds = master; // copy it if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) { perror("select"); exit(4); } // run through the existing connections looking for data // to read for(int i = 0; i <= fdmax; i++) { if (FD_ISSET(i, &read_fds)) { // we got one!! if (i == listener) handle_new_connection(i, &master, &fdmax); else handle_client_data(i, listener, &master, fdmax); } } } return 0; } ``` -------------------------------- ### Get Local Hostname with gethostname() in C Source: https://beej.us/guide/bgnet/html/index The gethostname() function retrieves the name of the local machine. It takes a character array to store the hostname and its size. Returns 0 on success and -1 on error. ```c #include int gethostname(char *hostname, size_t size); ``` -------------------------------- ### Get Hostname by IP Address (C) Source: https://beej.us/guide/bgnet/html/index Illustrates using gethostbyaddr to retrieve a hostname from an IP address. This function supports both IPv4 and IPv6 addresses. However, it is recommended to use getnameinfo() for modern applications. ```c struct hostent *he; struct in_addr ipv4addr; struct in6_addr ipv6addr; inet_pton(AF_INET, "192.0.2.34", &ipv4addr); he = gethostbyaddr(&ipv4addr, sizeof ipv4addr, AF_INET); printf("Host name: %s\n", he->h_name); inet_pton(AF_INET6, "2001:db8:63b3:1::beef", &ipv6addr); he = gethostbyaddr(&ipv6addr, sizeof ipv6addr, AF_INET6); printf("Host name: %s\n", he->h_name); ``` -------------------------------- ### Demonstration of Data Packing and Unpacking (C) Source: https://beej.us/guide/bgnet/html/index This C program demonstrates the usage of data packing and unpacking functions. It packs several data types into a buffer and then unpacks them into different variables, printing the results. It highlights the use of format specifiers and the importance of specifying maximum string lengths to prevent buffer overflows. ```c #include #include #include // If you have a C23 compiler #if __STDC_VERSION__ >= 202311L #include #else // Otherwise let's define our own. // Varies for different architectures! But you're probably: typedef float float32_t; typedef double float64_t; #endif int main(void) { uint8_t buf[1024]; int8_t magic; int16_t monkeycount; int32_t altitude; float32_t absurdityfactor; char *s = "Great unmitigated Zot! You've found the Runestaff!"; char s2[96]; int16_t packetsize, ps2; packetsize = pack(buf, "chhlsf", (int8_t)'B', (int16_t)0, (int16_t)37, (int32_t)-5, s, (float32_t)-3490.6677); packi16(buf+1, packetsize); // store packet size for kicks printf("packet is %" PRId32 " bytes\n", packetsize); unpack(buf, "chhl96sf", &magic, &ps2, &monkeycount, &altitude, s2, &absurdityfactor); printf("'%%c' %" PRId32" %" PRId16 " %" PRId32 " \"%s\" %f\n", magic, ps2, monkeycount, altitude, s2, absurdityfactor); } ``` -------------------------------- ### Float Serialization Usage Example (C) Source: https://beej.us/guide/bgnet/html/index Demonstrates the practical usage of the custom `htonf` and `ntohf` functions for serializing and deserializing a float. It shows the conversion process and prints the original, network, and unpacked float values. ```c #include int main(void) { float f = 3.1415926, f2; uint32_t netf; netf = htonf(f); // convert to "network" form f2 = ntohf(netf); // convert back to test printf("Original: %f\n", f); // 3.141593 printf(" Network: 0x%08X\n", netf); // 0x0003243F printf("Unpacked: %f\n", f2); // 3.141586 return 0; } ``` -------------------------------- ### C Server-side socket sequence: getaddrinfo(), socket(), bind(), listen() Source: https://beej.us/guide/bgnet/html/index This outlines the typical sequence of system calls for a server to prepare for listening for incoming connections. It involves resolving address information, creating a socket, binding it to a specific address and port, and then enabling it to listen for connections. ```c getaddrinfo(); socket(); bind(); listen(); /* accept() goes here */ ``` -------------------------------- ### C Stream Server Implementation for Sending 'Hello, world!' Source: https://beej.us/guide/bgnet/html/index This C code implements a basic stream socket server. It sets up a listening socket, accepts client connections, and sends the string 'Hello, world!' to each client. It uses standard POSIX socket APIs and includes signal handling for child processes. ```c #include #include #include #include #include #include #include #include #include #include #include #include #define PORT "3490" // the port users will be connecting to #define BACKLOG 10 // how many pending connections queue will hold void sigchld_handler(int s) { (void)s; // quiet unused variable warning // 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) { // listen on sock_fd, new connection on new_fd int sockfd, new_fd; struct addrinfo hints, *servinfo, *p; struct sockaddr_storage their_addr; // connector's address info 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; 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); exit(0); } close(new_fd); // parent doesn't need this } return 0; } ``` -------------------------------- ### Socket Options: getsockopt and setsockopt Source: https://beej.us/guide/bgnet/html/index This section covers the use of `getsockopt` and `setsockopt` to retrieve and set various options on a socket. It explains common options like `SO_BINDTODEVICE`, `SO_REUSEADDR`, and `SO_BROADCAST`, along with their parameters and behavior. ```APIDOC ## GET /setsockopt and GET /getsockopt ### Description These functions are used to get and set options on a socket. They allow for fine-grained control over socket behavior, such as binding to a specific network interface or allowing address reuse. ### Method `setsockopt` (set option), `getsockopt` (get option) ### Endpoint These are C library functions, not HTTP endpoints. ### Parameters #### `setsockopt` Parameters - **s** (int) - Required - The socket descriptor. - **level** (int) - Required - The protocol level for the option (e.g., `SOL_SOCKET`). - **optname** (int) - Required - The name of the option to set (e.g., `SO_REUSEADDR`, `SO_BINDTODEVICE`). - **optval** (const void *) - Required - A pointer to the value to set for the option. - **optlen** (socklen_t) - Required - The size of the `optval` buffer. #### `getsockopt` Parameters - **s** (int) - Required - The socket descriptor. - **level** (int) - Required - The protocol level for the option (e.g., `SOL_SOCKET`). - **optname** (int) - Required - The name of the option to retrieve (e.g., `SO_BROADCAST`). - **optval** (void *) - Required - A pointer to a buffer where the option's value will be stored. - **optlen** (socklen_t *) - Required - A pointer to a `socklen_t` that specifies the maximum size of the `optval` buffer and will be updated with the actual size of the retrieved option value. ### Common Options - **`SO_BINDTODEVICE`**: Binds the socket to a specific network interface (e.g., `eth0`). - **`SO_REUSEADDR`**: Allows the socket to bind to an address that is already in use by another socket, provided it's not actively listening. - **`SO_BROADCAST`**: Enables the use of broadcast messages for UDP sockets. ### Request Example (setsockopt) ```c int optval = 1; socklen_t optlen = sizeof(optval); // Set SO_REUSEADDR to true socklen_t result = setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &optval, optlen); char *device_name = "eth1"; optlen = 4; // Length of device name // Bind to a specific device (system dependent) result = setsockopt(socket_fd, SOL_SOCKET, SO_BINDTODEVICE, device_name, optlen); ``` ### Request Example (getsockopt) ```c int optval; socklen_t optlen = sizeof(optval); // Check if SO_BROADCAST is enabled got_optlen = sizeof(optval); socklen_t result = getsockopt(socket_fd, SOL_SOCKET, SO_BROADCAST, &optval, &got_optlen); if (optval != 0) { // SO_BROADCAST is enabled } ``` ### Response Returns zero on success, or -1 on error (and `errno` will be set accordingly). ``` -------------------------------- ### Get address information using getaddrinfo() in C Source: https://beej.us/guide/bgnet/html/index This C code illustrates the use of `getaddrinfo` to retrieve address information for a given host and service, populating a `struct addrinfo`. It also shows the related `freeaddrinfo` and `gai_strerror` functions. ```c #include #include #include int getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res); void freeaddrinfo(struct addrinfo *ai); const char *gai_strerror(int ecode); struct addrinfo { int ai_flags; // AI_PASSIVE, AI_CANONNAME, ... int ai_family; // AF_xxx int ai_socktype; // SOCK_xxx int ai_protocol; // 0 (auto) or IPPROTO_TCP, IPPROTO_UDP socklen_t ai_addrlen; // length of ai_addr char *ai_canonname; // canonical name for nodename struct sockaddr *ai_addr; // binary address struct addrinfo *ai_next; // next structure in linked list }; ```