b: new case, connect to client and receive->print his data
This commit is contained in:
189
src/b.cpp
Normal file
189
src/b.cpp
Normal file
@@ -0,0 +1,189 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_NO_MIN_MAX
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#pragma comment(lib, "ws2_32")
|
||||
#include "basic.cpp"
|
||||
|
||||
#define SERVER_NAME NULL
|
||||
#define SERVER_PORT "8000"
|
||||
|
||||
char *serialize(sockaddr *n) {
|
||||
char s[INET6_ADDRSTRLEN];
|
||||
void *addr = NULL;
|
||||
if (n->sa_family == AF_INET) {
|
||||
sockaddr_in* ipv4 = (sockaddr_in*)n;
|
||||
addr = &(ipv4->sin_addr);
|
||||
} else if (n->sa_family == AF_INET6) {
|
||||
sockaddr_in6* ipv6 = (sockaddr_in6*)n;
|
||||
addr = &(ipv6->sin6_addr);
|
||||
} else {
|
||||
return "<unhandled_case>";
|
||||
}
|
||||
const char *res = inet_ntop(n->sa_family, addr, s, sizeof(s));
|
||||
assert(res != NULL);
|
||||
return strf("%s", s);
|
||||
}
|
||||
|
||||
int wrapped_close_socket(SOCKET socket) {
|
||||
int err = closesocket(socket);
|
||||
if (err == SOCKET_ERROR) {
|
||||
panicf("server: failed to close socket: %s", wsa_error());
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void run_server() {
|
||||
struct addrinfo *infos = {};
|
||||
struct addrinfo hints = {};
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
int err = getaddrinfo(SERVER_NAME, SERVER_PORT, &hints, &infos);
|
||||
if (err != 0) {
|
||||
panicf("server: getaddrinfo failed, error code: %d", gai_strerrorA(err));
|
||||
}
|
||||
defer { freeaddrinfo(infos); };
|
||||
|
||||
SOCKET sock = -1;
|
||||
for (addrinfo *it = infos; it; it = it->ai_next) {
|
||||
sock = socket(it->ai_family, it->ai_socktype, it->ai_protocol);
|
||||
if (sock == -1) {
|
||||
debugf("server: skipping socket call: %s", wsa_error());
|
||||
continue;
|
||||
}
|
||||
|
||||
err = bind(sock, it->ai_addr, (int)it->ai_addrlen);
|
||||
if (err != 0) {
|
||||
debugf("server: bind failed: %s", wsa_error());
|
||||
sock = wrapped_close_socket(sock);
|
||||
continue;
|
||||
}
|
||||
|
||||
debugf("server: bind to %s", serialize(it->ai_addr));
|
||||
break;
|
||||
}
|
||||
|
||||
if (sock == -1) {
|
||||
panicf("server: failed to bind to a port!");
|
||||
}
|
||||
defer { wrapped_close_socket(sock); };
|
||||
|
||||
int max_pending_connections = 10;
|
||||
err = listen(sock, max_pending_connections);
|
||||
if (err != 0) { panicf("server: listen failed: %s", wsa_error()); }
|
||||
|
||||
sockaddr_storage client_sockaddr = {};
|
||||
int sockaddr_len = sizeof(client_sockaddr);
|
||||
SOCKET client_sock = accept(sock, (sockaddr *)&client_sockaddr, &sockaddr_len);
|
||||
if (client_sock == -1) {
|
||||
panicf("server: failed to accept connection %s", wsa_error());
|
||||
}
|
||||
defer { wrapped_close_socket(client_sock); };
|
||||
|
||||
for (;;) {
|
||||
char buff[1024];
|
||||
int bytes = recv(client_sock, buff, lengthof(buff) - 1, 0);
|
||||
if (bytes == -1) {
|
||||
panicf("server: failed recv %s", wsa_error());
|
||||
}
|
||||
debugf("server: %.*s", bytes, buff);
|
||||
|
||||
if (bytes == 4 && buff[0] == 'q' && buff[1] == 'u' && buff[2] == 'i' && buff[3] == 't') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
debugf("server: exiting");
|
||||
}
|
||||
|
||||
void run_client() {
|
||||
struct addrinfo *infos = {};
|
||||
struct addrinfo hints = {};
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
int err = getaddrinfo(SERVER_NAME, SERVER_PORT, &hints, &infos);
|
||||
if (err != 0) {
|
||||
panicf("client: getaddrinfo failed, error code: %d", gai_strerrorA(err));
|
||||
}
|
||||
defer { freeaddrinfo(infos); };
|
||||
|
||||
SOCKET sock = -1;
|
||||
for (addrinfo *it = infos; it; it = it->ai_next) {
|
||||
sock = socket(it->ai_family, it->ai_socktype, it->ai_protocol);
|
||||
if (sock == -1) {
|
||||
debugf("client: skipping socket call: %s", wsa_error());
|
||||
continue;
|
||||
}
|
||||
|
||||
err = connect(sock, it->ai_addr, (int)it->ai_addrlen);
|
||||
if (err != 0) {
|
||||
debugf("client: failed to connect %s", wsa_error());
|
||||
sock = wrapped_close_socket(sock);
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (sock == -1) {
|
||||
panicf("client: failed to connect %s", wsa_error());
|
||||
}
|
||||
defer { wrapped_close_socket(sock); };
|
||||
|
||||
for (;;) {
|
||||
const char *buff = "hello world!";
|
||||
int buff_size = (int)strlen(buff);
|
||||
int bytes = send(sock, buff, buff_size, 0);
|
||||
// bytes can be less then buffer and that needs to be handled
|
||||
// that is the remaining amount needs to be sent?
|
||||
if (bytes == SOCKET_ERROR) {
|
||||
debugf("client: failed to send %s", wsa_error());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct Thread_Context {
|
||||
int idx;
|
||||
};
|
||||
|
||||
DWORD thread_entry(void *param) {
|
||||
Thread_Context *ctx = (Thread_Context *)param;
|
||||
if (ctx->idx == 0) {
|
||||
run_server();
|
||||
} else {
|
||||
run_client();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
WSADATA wsaData;
|
||||
int err = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
if (err != 0) {
|
||||
panicf("WSAStartup failed: %s", serialize_windows_error(err));
|
||||
}
|
||||
defer { WSACleanup(); };
|
||||
|
||||
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
|
||||
panicf("Version 2.2 of Winsock not available");
|
||||
}
|
||||
|
||||
constexpr int thread_count = 2;
|
||||
HANDLE thread_handles[thread_count] = {};
|
||||
DWORD thread_ids[thread_count] = {};
|
||||
Thread_Context thread_datas[thread_count] = {};
|
||||
for (int i = 0; i < thread_count; i += 1) {
|
||||
Thread_Context *ctx = thread_datas + i;
|
||||
ctx->idx = i;
|
||||
LPSECURITY_ATTRIBUTES attribs = NULL;
|
||||
thread_handles[i] = CreateThread(attribs, 0, thread_entry, thread_datas + i, 0, thread_ids + i);
|
||||
}
|
||||
WaitForMultipleObjects(thread_count, thread_handles, TRUE, INFINITE);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user