Last active
January 16, 2024 14:36
-
-
Save mmj-the-fighter/5232483f1b5f7cd9033b92ec2f3edf0d to your computer and use it in GitHub Desktop.
server and client for udp broadcasting, useful for server discovery.
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
#if defined(_WIN32) | |
#define BUILD_FOR_WINDOWS | |
#endif | |
#ifdef BUILD_FOR_WINDOWS | |
#pragma warning(disable:4996) | |
#define _WINSOCK_DEPRECATED_NO_WARNINGS | |
#endif | |
#include <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <time.h> | |
#ifdef BUILD_FOR_WINDOWS | |
#include <ws2tcpip.h> | |
#include <winsock.h> | |
#pragma comment (lib, "wsock32.lib") | |
#pragma comment(lib, "Ws2_32.lib") | |
#else | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <sys/un.h> | |
#include <netinet/in.h> | |
#include <arpa/inet.h> | |
#include <netdb.h> | |
#include <errno.h> | |
#include <unistd.h> | |
#endif | |
#include "common.h" | |
///////////////////////////////////////////////////////////// | |
char *program_name = "broadcastclient"; | |
#ifdef BUILD_FOR_WINDOWS | |
WSADATA wsaData; | |
#endif | |
struct sockaddr_in si_me, si_other; | |
int socket_handle, slen = sizeof(si_other); | |
char buf[BUFLEN]; | |
int choice = 0; | |
struct packet packet; | |
int broadcast = 1; | |
int conn_termination_request_len; | |
///////////////////////////////////////////////////////////// | |
void init_lengths(); | |
void init_socket_lib(); | |
void create_socket(); | |
void fill_in_address(); | |
void set_socket_to_broadcasting_mode(); | |
void send_request(); | |
void receive_response(); | |
void resolve_ip_and_interpret_packet(); | |
void cleanup(); | |
///////////////////////////////////////////////////////////// | |
int main(int argc, char* argv[]) | |
{ | |
printf("%s\n", program_name); | |
#ifdef BUILD_FOR_WINDOWS | |
init_socket_lib(); | |
#endif | |
create_socket(); | |
fill_in_address(); | |
set_socket_to_broadcasting_mode(); | |
init_lengths(); | |
while (1) { | |
printf("Enter a number ( enter 0 to quit) :"); | |
scanf("%d", &choice); | |
if (choice == 0) { | |
strncpy(buf, conn_termination_request, conn_termination_request_len); | |
send_request(); | |
break; | |
} | |
strncpy(buf, "sendmeserverinfo", BUFLEN); | |
printf("Sending request...\n"); | |
send_request(); | |
printf("Waiting for response...\n"); | |
receive_response(); | |
resolve_ip_and_interpret_packet(); | |
} | |
cleanup(); | |
return 0; | |
} | |
///////////////////////////////////////////////////////////// | |
void init_socket_lib() | |
{ | |
#ifdef BUILD_FOR_WINDOWS | |
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) { | |
printf("\nWSAStartup() failed; WSAGetLastError() returns %d", WSAGetLastError()); | |
exit(1); | |
} | |
#endif | |
} | |
void create_socket() | |
{ | |
if ((socket_handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { | |
#ifdef BUILD_FOR_WINDOWS | |
printf("\nsocket() failed; WSAGetLastError() returns %d", WSAGetLastError()); | |
WSACleanup(); | |
#else | |
printf("\nsocket() failed; errno: %d", errno); | |
#endif | |
exit(1); | |
} | |
} | |
void fill_in_address() | |
{ | |
memset((char *)&si_other, 0, sizeof(si_me)); | |
si_other.sin_family = AF_INET; | |
si_other.sin_port = htons(PORT); | |
si_other.sin_addr.s_addr = htonl(INADDR_BROADCAST); | |
} | |
void set_socket_to_broadcasting_mode() | |
{ | |
if (setsockopt(socket_handle, SOL_SOCKET, SO_BROADCAST, (const char *)&broadcast, sizeof broadcast) == -1) { | |
#ifdef BUILD_FOR_WINDOWS | |
printf("\nsetsockopt (SO_BROADCAST) failed; WSAGetLastError() returns %d", WSAGetLastError()); | |
closesocket(socket_handle); | |
WSACleanup(); | |
#else | |
perror("setsockopt (SO_BROADCAST)"); | |
close(socket_handle); | |
#endif | |
exit(1); | |
} | |
} | |
void init_lengths() | |
{ | |
conn_termination_request_len = strlen(conn_termination_request); | |
} | |
void send_request() | |
{ | |
if (sendto(socket_handle, buf, BUFLEN, 0, (struct sockaddr*)&si_other, slen) == -1) { | |
#ifdef BUILD_FOR_WINDOWS | |
printf("\nsendto() failed; WSAGetLastError() returns %d", WSAGetLastError()); | |
closesocket(socket_handle); | |
WSACleanup(); | |
#else | |
perror("sendto() failed"); | |
close(socket_handle); | |
#endif | |
exit(1); | |
} | |
} | |
void receive_response() | |
{ | |
if (recvfrom(socket_handle, &packet, sizeof(struct packet), 0, (struct sockaddr*)&si_other, &slen) == -1) { | |
#ifdef BUILD_FOR_WINDOWS | |
printf("\recvfrom() failed; WSAGetLastError() returns %d", WSAGetLastError()); | |
closesocket(socket_handle); | |
WSACleanup(); | |
#else | |
perror("recvfrom() failed"); | |
close(socket_handle); | |
#endif | |
exit(1); | |
} | |
} | |
void resolve_ip_and_interpret_packet() | |
{ | |
int server_id = packet.server_id; | |
char *server_ip = inet_ntoa(si_other.sin_addr); | |
int server_port = packet.server_port; | |
char *server_name = packet.server_name; | |
char *server_time = packet.time_now; | |
printf("\nserver_id: %d\n", server_id); | |
printf("server_port: %d\n", server_port); | |
printf("server_ip: %s\n", server_ip); | |
printf("server_name: %s\n", server_name); | |
printf("server_time: %s\n", server_time); | |
} | |
void cleanup() | |
{ | |
#ifdef BUILD_FOR_WINDOWS | |
closesocket(socket_handle); | |
WSACleanup(); | |
#else | |
close(socket_handle); | |
#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
#if defined(_WIN32) | |
#define BUILD_FOR_WINDOWS | |
#endif | |
#ifdef BUILD_FOR_WINDOWS | |
#pragma warning(disable:4996) | |
#define _WINSOCK_DEPRECATED_NO_WARNINGS | |
#endif | |
#include <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <time.h> | |
#ifdef BUILD_FOR_WINDOWS | |
#include <ws2tcpip.h> | |
#include <winsock.h> | |
#pragma comment (lib, "wsock32.lib") | |
#pragma comment(lib, "Ws2_32.lib") | |
#else | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <sys/un.h> | |
#include <netinet/in.h> | |
#include <arpa/inet.h> | |
#include <netdb.h> | |
#include <errno.h> | |
#include <unistd.h> | |
#endif | |
#include "common.h" | |
////////////////////////////////////////////////// | |
char *program_name = "broadcastserver"; | |
struct sockaddr_in si_me, si_other; | |
int socket_handle, slen = sizeof(si_other); | |
char request_buffer[BUFLEN]; | |
time_t tmt; | |
struct packet response_packet; | |
int broadcast = 1; | |
/////////////////////////////////////////////// | |
char *request_origin_ip; | |
int conn_termination_request_len; | |
const char* server_name = "fictious server"; | |
int server_id = 1729; | |
int server_port = 65000; | |
#ifdef BUILD_FOR_WINDOWS | |
WSADATA wsaData; | |
#endif | |
/////////////////////////////////////////////// | |
void init_lengths(); | |
void init_socket_lib(); | |
void create_socket(); | |
void fill_in_address(); | |
void set_socket_to_broadcasting_mode(); | |
void bind_socket(); | |
void receive_request(); | |
void resolve_ip_of_request(); | |
int check_if_disconnect_request_came(); | |
void prepare_response(); | |
void send_response(); | |
void cleanup(); | |
//////////////////////////////////////////////// | |
int main(int argc, char* argv[]) | |
{ | |
printf("%s\n", program_name); | |
#ifdef BUILD_FOR_WINDOWS | |
init_socket_lib(); | |
#endif | |
create_socket(); | |
fill_in_address(); | |
set_socket_to_broadcasting_mode(); | |
bind_socket(); | |
init_lengths(); | |
while (1) { | |
printf("Waiting for request...\n"); | |
receive_request(); | |
resolve_ip_of_request(); | |
printf("Request from ip %s came: %s\n", request_origin_ip, request_buffer); | |
if (check_if_disconnect_request_came()) { | |
break; | |
} | |
printf("Preparing response...\n"); | |
prepare_response(); | |
printf("Sending response...\n"); | |
send_response(); | |
printf("Response sent\n"); | |
} | |
cleanup(); | |
return 0; | |
} | |
/////////////////////////////////////////////////////////// | |
void init_lengths() | |
{ | |
conn_termination_request_len = strlen(conn_termination_request); | |
} | |
void init_socket_lib() | |
{ | |
#ifdef BUILD_FOR_WINDOWS | |
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) { | |
printf("\nWSAStartup() failed; WSAGetLastError() returns %d", WSAGetLastError()); | |
exit(1); | |
} | |
#endif | |
} | |
void create_socket() | |
{ | |
if ((socket_handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { | |
#ifdef BUILD_FOR_WINDOWS | |
printf("\nsocket() failed; WSAGetLastError() returns %d", WSAGetLastError()); | |
WSACleanup(); | |
#else | |
printf("\nsocket() failed; errno: %d", errno); | |
#endif | |
exit(1); | |
} | |
} | |
void fill_in_address() | |
{ | |
memset((char *)&si_me, 0, sizeof(si_me)); | |
si_me.sin_family = AF_INET; | |
si_me.sin_port = htons(PORT); | |
si_me.sin_addr.s_addr = htonl(INADDR_ANY); | |
} | |
void set_socket_to_broadcasting_mode() | |
{ | |
if (setsockopt(socket_handle, SOL_SOCKET, SO_BROADCAST, (const char *)&broadcast, sizeof broadcast) == -1) { | |
#ifdef BUILD_FOR_WINDOWS | |
printf("\nsetsockopt (SO_BROADCAST) failed; WSAGetLastError() returns %d", WSAGetLastError()); | |
closesocket(socket_handle); | |
WSACleanup(); | |
#else | |
perror("setsockopt (SO_BROADCAST)"); | |
close(socket_handle); | |
#endif | |
exit(1); | |
} | |
} | |
void bind_socket() | |
{ | |
if (bind(socket_handle, (struct sockaddr*)&si_me, sizeof(si_me)) == -1) { | |
#ifdef BUILD_FOR_WINDOWS | |
printf("\nbind failed; WSAGetLastError() returns %d", WSAGetLastError()); | |
closesocket(socket_handle); | |
WSACleanup(); | |
#else | |
perror("bind"); | |
close(socket_handle); | |
#endif | |
exit(1); | |
} | |
} | |
void receive_request() | |
{ | |
if (recvfrom(socket_handle, request_buffer, BUFLEN, 0, (struct sockaddr*)&si_other, &slen) == -1) { | |
#ifdef BUILD_FOR_WINDOWS | |
printf("\recvfrom() failed; WSAGetLastError() returns %d", WSAGetLastError()); | |
closesocket(socket_handle); | |
WSACleanup(); | |
#else | |
perror("recvfrom() failed"); | |
close(socket_handle); | |
#endif | |
exit(1); | |
} | |
} | |
void resolve_ip_of_request() | |
{ | |
request_origin_ip = inet_ntoa(si_other.sin_addr); | |
} | |
int check_if_disconnect_request_came() | |
{ | |
if (!strncmp(request_buffer, conn_termination_request, conn_termination_request_len)) { | |
return 1; | |
} | |
return 0; | |
} | |
void prepare_response() | |
{ | |
response_packet.server_id = 1729; | |
response_packet.server_port = 65000; | |
strncpy(response_packet.server_name, server_name, NAMEMAXLEN); | |
tmt = time(NULL); | |
strncpy(response_packet.time_now, ctime(&tmt), TIMEMAXLEN); | |
} | |
void send_response() | |
{ | |
if (sendto(socket_handle, (struct packet *)&response_packet, sizeof(struct packet), 0, (struct sockaddr*)&si_other, slen) == -1) { | |
#ifdef BUILD_FOR_WINDOWS | |
printf("\nsendto() failed; WSAGetLastError() returns %d", WSAGetLastError()); | |
closesocket(socket_handle); | |
WSACleanup(); | |
#else | |
perror("sendto() failed"); | |
close(socket_handle); | |
#endif | |
exit(1); | |
} | |
} | |
void cleanup() | |
{ | |
#ifdef BUILD_FOR_WINDOWS | |
closesocket(socket_handle); | |
WSACleanup(); | |
#else | |
close(socket_handle); | |
#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
#ifndef _COMMON_H_ | |
#define _COMMON_H_ | |
#define PORT 8888 | |
#define BUFLEN 512 | |
#define TIMEMAXLEN 64 | |
#define NAMEMAXLEN 64 | |
struct packet | |
{ | |
int server_id; | |
int server_port; | |
char server_name[NAMEMAXLEN]; | |
char time_now[TIMEMAXLEN]; | |
}; | |
const char* conn_termination_request = "quit"; | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment