Created
January 29, 2024 17:10
-
-
Save avelican/7fd79e57989db30761b7bf323787d334 to your computer and use it in GitHub Desktop.
Noob's attempt: Cross Platform UDP (Linux + Windows)
This file contains hidden or 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 <sys/types.h> | |
#ifdef _WIN32 | |
#define WIN32_LEAN_AND_MEAN // prevent import of WinSock ? (conflict with WinSock2) | |
#include <windows.h> // sleep() | |
#define sleep(n) Sleep((n) * 1000) | |
#include <winsock2.h> | |
#include <ws2tcpip.h> | |
# define close closesocket | |
#else | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#include <arpa/inet.h> | |
#include <unistd.h> // sleep() | |
#endif | |
void main(int argc, char **argv){ | |
if(argc != 2){ | |
printf("Usage: %s <port>\n", argv[0]); | |
exit(0); | |
} | |
#ifdef _WIN32 | |
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 is not available.\n"); | |
WSACleanup(); | |
exit(2); | |
} | |
#endif | |
int port = atoi(argv[1]); | |
int sockfd; | |
struct sockaddr_in serverAddr; | |
char buffer[1024]; | |
socklen_t addr_size; | |
sockfd = socket(PF_INET, SOCK_DGRAM, 0); | |
memset(&serverAddr, '\0', sizeof(serverAddr)); | |
serverAddr.sin_family = AF_INET; | |
serverAddr.sin_port = htons(port); | |
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); | |
strcpy(buffer, "Hello Server\n"); | |
while(1){ | |
// sendto(sockfd, buffer, 1024, 0, (struct sockaddr*)&serverAddr, sizeof(serverAddr)); | |
sendto(sockfd, buffer, 1024, 0, (struct sockaddr*)&serverAddr, sizeof(serverAddr)); | |
printf("[+]Data Send: %s", buffer); | |
sleep(1); | |
} | |
close(sockfd); | |
} |
This file contains hidden or 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 <sys/types.h> | |
#ifdef _WIN32 | |
# define WIN32_LEAN_AND_MEAN | |
# include <windows.h> | |
# define sleep(n) Sleep((n) * 1000) | |
# include <winsock2.h> | |
# include <ws2tcpip.h> | |
# define close closesocket | |
#else | |
# include <sys/socket.h> | |
# include <netinet/in.h> | |
# include <arpa/inet.h> | |
# include <unistd.h> // sleep() | |
#endif | |
void net_init() { | |
printf("Server starting.\n"); | |
#ifdef _WIN32 | |
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 is not available.\n"); | |
WSACleanup(); | |
exit(2); | |
} | |
#endif | |
} | |
void net_exit() { | |
#ifdef _WIN32 | |
WSACleanup(); | |
#endif | |
} | |
void main(int argc, char **argv){ | |
// if(argc != 2){ | |
// printf("Usage: %s <port>\n", argv[0]); | |
// exit(0); | |
// } | |
char* address = "127.0.0.1"; | |
char* port_str = "1111"; | |
net_init(); | |
// int port = atoi(argv[1]); | |
int port = atoi(port_str); | |
// TODO: make global; move to net_init()? | |
int sockfd; | |
struct sockaddr_in si_me, si_other; | |
char buffer[1024]; // TODO: how to queue messages in and out? | |
socklen_t addr_size; | |
sockfd = socket(AF_INET, SOCK_DGRAM, 0); | |
memset(&si_me, '\0', sizeof(si_me)); | |
si_me.sin_family = AF_INET; | |
si_me.sin_port = htons(port); | |
// si_me.sin_addr.s_addr = inet_addr("127.0.0.1"); | |
// inet_aton("127.0.0.1", si_me.sin_addr); // doesn't work on windows.. sigh | |
inet_pton(AF_INET, address, &si_me.sin_addr.s_addr); | |
// NOTE: Can also use AF_INET6 | |
// https://stackoverflow.com/questions/23187496/what-is-the-meaning-of-sin-addr-s-addr-and-inet-addr | |
// inet_addr was deprecated in favour of inet_aton even before IPv6 come into play because it's a poorly designed API call. It signals an error by returning INADDR_NONE (-1) but its return type in_addr_t is actually an unsigned integer, which makes passing the signed -1 very compiler-dependent. Also on machines with two's complement representation of negative numbers (that's most computer architectures nowadays) INADDR_NONE equals INADDR_BROADCAST (255.255.255.255). | |
/////////// | |
// kept becaue funny | |
// int bindstatus = bind(sockfd, (struct sockaddr*)&si_me, sizeof(si_me)); | |
// if (bindstatus !=0 ) { | |
// #ifdef _WIN32 // sigh | |
// int WS_err = WSAGetLastError(); | |
// if (WS_err == WSAEADDRINUSE) { | |
// #else | |
// if (errno == EADDRINUSE) { | |
// #endif | |
// // for local usage. If port used, try next port | |
// printf("port %d taken... trying %d", port, port+1); | |
// port++; | |
// si_me.sin_port = htons(port); | |
// int bindstatus2 = bind(sockfd, (struct sockaddr*)&si_me, sizeof(si_me)); | |
// if (bindstatus2 != 0) { | |
// #ifdef _WIN32 | |
// int WS_err = WSAGetLastError(); // note: shadowed in nested block | |
// printf("Could not bind to port. WS_err: %d", WS_err); | |
// #else | |
// printf("Could not bind to port. errno: %d", errno); | |
// #endif | |
// exit(1); | |
// } | |
// } else { | |
// #ifdef _WIN32 | |
// int WS_err = WSAGetLastError(); // note: shadowed in nested block | |
// printf("Could not bind to port. WS_err: %d", WS_err); | |
// #else | |
// printf("Could not bind to port. errno: %d", errno); | |
// #endif | |
// exit(1); | |
// } | |
// } | |
#ifdef _WIN32 | |
int bindstatus = bind(sockfd, (struct sockaddr*)&si_me, sizeof(si_me)); | |
if (bindstatus !=0 ) { | |
int WS_err = WSAGetLastError(); | |
if (WS_err == WSAEADDRINUSE) { | |
// for local usage. If port used, try next port | |
printf("port %d taken... trying %d", port, port+1); | |
port++; | |
si_me.sin_port = htons(port); | |
int bindstatus2 = bind(sockfd, (struct sockaddr*)&si_me, sizeof(si_me)); | |
if (bindstatus2 != 0) { | |
int WS_err = WSAGetLastError(); // note: shadowed in nested block | |
printf("Could not bind to port. WS_err: %d", WS_err); | |
exit(1); | |
} | |
} else { | |
int WS_err = WSAGetLastError(); // note: shadowed in nested block | |
printf("Could not bind to port. WS_err: %d", WS_err); | |
exit(1); | |
} | |
} | |
#else | |
int bindstatus = bind(sockfd, (struct sockaddr*)&si_me, sizeof(si_me)); | |
if (bindstatus !=0 ) { | |
if (errno == EADDRINUSE) { | |
// for local usage. If port used, try next port | |
printf("port %d taken... trying %d", port, port+1); | |
port++; | |
si_me.sin_port = htons(port); | |
int bindstatus2 = bind(sockfd, (struct sockaddr*)&si_me, sizeof(si_me)); | |
if (bindstatus2 != 0) { | |
printf("Could not bind to port. errno: %d", errno); | |
exit(1); | |
} | |
} else { | |
printf("Could not bind to port. errno: %d", errno); | |
exit(1); | |
} | |
} | |
#endif | |
addr_size = sizeof(si_other); | |
printf("Server started. Listening on %s:%d", address, port); | |
while(1){ | |
int recvstat = recvfrom(sockfd, buffer, 1024, 0, (struct sockaddr*)(struct sockaddr*)& si_other, &addr_size); | |
if (recvstat < 0) | |
{ | |
printf("*** ERROR - recvfrom() failed \n"); | |
exit(-1); | |
} else { | |
printf("[+]Data Received: %s", buffer); | |
printf(" FROM: %s:%d", inet_ntoa(si_other.sin_addr), si_other.sin_port); | |
} | |
} | |
close(sockfd); | |
net_exit(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment