Last active
November 16, 2023 19:54
-
-
Save henkman/1ddbc8ad6c5efe23b6d791e5304afd5a to your computer and use it in GitHub Desktop.
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
/** | |
// SAMPLE | |
int main(void) { | |
SocketInit(); | |
struct sockaddr_in addr; | |
SocketResolve(&addr, "localhost", 5432); | |
Socket sock = SocketUDP(false); | |
// connected udp can use send/recv instead of sendto/recvfrom | |
connect(sock, (const struct sockaddr *) &addr, sizeof(addr)); | |
const char *data = "hello world"; | |
send(sock, data, strlen(data), 0); | |
struct timeval timeout = {0}; | |
timeout.tv_sec = 4; | |
if(SocketReadable(sock, &timeout) > 0) { | |
uint8_t buf[8*1024]; | |
int received = recv(sock, buf, 8*1024, 0); | |
if(received > 0) { | |
printf("%.*s\n", received, buf); | |
} | |
} | |
SocketClose(sock); | |
SocketQuit(); | |
return 0; | |
} | |
*/ | |
#include <netinet/in.h> | |
#ifdef _WIN32 | |
#include <Ws2tcpip.h> | |
#include <winsock2.h> | |
typedef SOCKET Socket; | |
#else | |
#include <arpa/inet.h> | |
#include <fcntl.h> | |
#include <netdb.h> | |
#include <sys/socket.h> | |
#include <unistd.h> | |
typedef int Socket; | |
#endif | |
// returns 0 on success | |
static int SocketInit(void) { | |
#ifdef _WIN32 | |
WSADATA wsa_data; | |
return WSAStartup(MAKEWORD(1, 1), &wsa_data); | |
#else | |
return 0; | |
#endif | |
} | |
// returns 0 on success | |
static int SocketQuit(void) { | |
#ifdef _WIN32 | |
return WSACleanup(); | |
#else | |
return 0; | |
#endif | |
} | |
// returns 0 on success | |
static int SocketResolve(struct sockaddr_in *addr, char *host, uint16_t port) { | |
struct hostent *h = gethostbyname(host); | |
if (h == NULL) { | |
return 1; | |
} | |
addr->sin_family = h->h_addrtype; | |
memcpy((char *)&(addr->sin_addr), h->h_addr, h->h_length); | |
addr->sin_port = htons(port); | |
return 0; | |
} | |
// SocketBind(sock, INADDR_ANY, port) to receive from everybody on port | |
// returns 0 on success | |
static int SocketBind(Socket sock, unsigned long address, uint16_t port) { | |
struct sockaddr_in server = {0}; | |
server.sin_family = AF_INET; | |
server.sin_addr.s_addr = htonl(address); | |
server.sin_port = htons(port); | |
return bind(sock, (struct sockaddr *)&server, sizeof(server)); | |
} | |
// returns positive on success | |
static Socket SocketUDP(bool blocking) { | |
Socket s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); | |
if (!blocking) { | |
fcntl(s, F_SETFL, O_NONBLOCK); | |
} | |
return s; | |
} | |
// returns positive on success | |
static Socket SocketTCP(bool blocking) { | |
Socket s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |
if (!blocking) { | |
fcntl(s, F_SETFL, O_NONBLOCK); | |
} | |
return s; | |
} | |
// returns 0 on timeout, positive value on success | |
static int SocketReadable(Socket sock, struct timeval *timeout) { | |
fd_set socks; | |
FD_ZERO(&socks); | |
FD_SET(sock, &socks); | |
return select(sock + 1, &socks, NULL, NULL, timeout); | |
} | |
static void SocketClose(Socket sock) { | |
#ifdef _WIN32 | |
closesocket(sock); | |
#else | |
close(sock); | |
#endif | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment