Polling and handling connections + messages at the same time
This commit is contained in:
84
src/b.cpp
84
src/b.cpp
@@ -37,6 +37,25 @@ int wrapped_close_socket(SOCKET socket) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_non_blocking(SOCKET sock) {
|
||||||
|
u_long mode = 1;
|
||||||
|
int err = ioctlsocket(sock, FIONBIO, &mode);
|
||||||
|
if (err != 0) {
|
||||||
|
panicf("server: failed to set nonblocking mode %s", wsa_error());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_no_delay(SOCKET sock) {
|
||||||
|
// Disable Nagle's algorithm, this would combine some of the packets together and these would
|
||||||
|
// get received on server side in one combined buffer. Two stacked 'hello world', the horror!
|
||||||
|
// This only finally worked when I set it on ALL the sockets, including the one in client.
|
||||||
|
int nodelay = 0;
|
||||||
|
int err = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay));
|
||||||
|
if (err != 0) {
|
||||||
|
panicf("server: failed to setsockopt %s", wsa_error());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void run_server() {
|
void run_server() {
|
||||||
struct addrinfo *infos = {};
|
struct addrinfo *infos = {};
|
||||||
struct addrinfo hints = {};
|
struct addrinfo hints = {};
|
||||||
@@ -72,31 +91,62 @@ void run_server() {
|
|||||||
panicf("server: failed to bind to a port!");
|
panicf("server: failed to bind to a port!");
|
||||||
}
|
}
|
||||||
defer { wrapped_close_socket(sock); };
|
defer { wrapped_close_socket(sock); };
|
||||||
|
set_no_delay(sock);
|
||||||
|
set_non_blocking(sock);
|
||||||
|
|
||||||
int max_pending_connections = 10;
|
int max_pending_connections = 10;
|
||||||
err = listen(sock, max_pending_connections);
|
err = listen(sock, max_pending_connections);
|
||||||
if (err != 0) { panicf("server: listen failed: %s", wsa_error()); }
|
if (err != 0) { panicf("server: listen failed: %s", wsa_error()); }
|
||||||
|
|
||||||
sockaddr_storage client_sockaddr = {};
|
WSAPOLLFD pfds[256] = {};
|
||||||
int sockaddr_len = sizeof(client_sockaddr);
|
int pfd_count = 0;
|
||||||
SOCKET client_sock = accept(sock, (sockaddr *)&client_sockaddr, &sockaddr_len);
|
{
|
||||||
if (client_sock == -1) {
|
pfds[pfd_count].fd = sock;
|
||||||
panicf("server: failed to accept connection %s", wsa_error());
|
pfds[pfd_count].events = POLLIN;
|
||||||
|
pfd_count += 1;
|
||||||
}
|
}
|
||||||
defer { wrapped_close_socket(client_sock); };
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char buff[1024];
|
int timeout = -1;
|
||||||
int bytes = recv(client_sock, buff, lengthof(buff) - 1, 0);
|
int poll_count = WSAPoll(pfds, pfd_count, timeout);
|
||||||
if (bytes == -1) {
|
if (poll_count == -1) {
|
||||||
panicf("server: failed recv %s", wsa_error());
|
panicf("server: failed to poll %s", wsa_error());
|
||||||
}
|
}
|
||||||
debugf("server: %.*s", bytes, buff);
|
|
||||||
|
|
||||||
if (bytes == 4 && buff[0] == 'q' && buff[1] == 'u' && buff[2] == 'i' && buff[3] == 't') {
|
for (int i = 0; i < pfd_count; i += 1) {
|
||||||
break;
|
bool ok = pfds[i].revents & (POLLIN | POLLHUP);
|
||||||
|
if (!ok) continue;
|
||||||
|
|
||||||
|
// Handle new connection or receive data
|
||||||
|
if (pfds[i].fd == sock) {
|
||||||
|
sockaddr_storage addr = {};
|
||||||
|
int sockaddr_len = sizeof(addr);
|
||||||
|
SOCKET client_sock = accept(sock, (sockaddr *)&addr, &sockaddr_len);
|
||||||
|
if (client_sock == -1) {
|
||||||
|
panicf("server: failed to accept connection %s", wsa_error());
|
||||||
|
}
|
||||||
|
set_no_delay(client_sock);
|
||||||
|
pfds[i].fd = client_sock;
|
||||||
|
pfds[i].events = POLLIN;
|
||||||
|
pfds[i].revents = 0;
|
||||||
|
pfd_count += 1;
|
||||||
|
|
||||||
|
debugf("server: new connection from: %s", serialize((sockaddr *)&addr));
|
||||||
|
} else {
|
||||||
|
char buff[1024];
|
||||||
|
int bytes = recv(pfds[i].fd, 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");
|
debugf("server: exiting");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,16 +184,20 @@ void run_client() {
|
|||||||
}
|
}
|
||||||
defer { wrapped_close_socket(sock); };
|
defer { wrapped_close_socket(sock); };
|
||||||
|
|
||||||
|
set_no_delay(sock);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const char *buff = "hello world!";
|
const char *buff = "hello world!";
|
||||||
int buff_size = (int)strlen(buff);
|
int buff_size = (int)strlen(buff);
|
||||||
|
debugf("client: sending %s", buff);
|
||||||
int bytes = send(sock, buff, buff_size, 0);
|
int bytes = send(sock, buff, buff_size, 0);
|
||||||
|
debugf("bytes sent: %d", bytes);
|
||||||
|
|
||||||
// bytes can be less then buffer and that needs to be handled
|
// bytes can be less then buffer and that needs to be handled
|
||||||
// that is the remaining amount needs to be sent?
|
// that is the remaining amount needs to be sent?
|
||||||
if (bytes == SOCKET_ERROR) {
|
if (bytes == SOCKET_ERROR) {
|
||||||
debugf("client: failed to send %s", wsa_error());
|
debugf("client: failed to send %s", wsa_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -174,7 +228,7 @@ int main() {
|
|||||||
panicf("Version 2.2 of Winsock not available");
|
panicf("Version 2.2 of Winsock not available");
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr int thread_count = 2;
|
constexpr int thread_count = 8;
|
||||||
HANDLE thread_handles[thread_count] = {};
|
HANDLE thread_handles[thread_count] = {};
|
||||||
DWORD thread_ids[thread_count] = {};
|
DWORD thread_ids[thread_count] = {};
|
||||||
Thread_Context thread_datas[thread_count] = {};
|
Thread_Context thread_datas[thread_count] = {};
|
||||||
|
|||||||
Reference in New Issue
Block a user