6. echo (serial, betterC)
import core.sys.linux.fcntl, core.sys.linux.errno, core.sys.linux.netinet.tcp, core.sys.linux.netinet.in_, core.sys.posix.sys.socket, core.sys.posix.unistd, core.sys.posix.netdb; import core.stdc.stdio; import core.stdc.string : strerror; int server(ushort port) { sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr("127.0.0.1"); addr.sin_port = htons(port); int fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) return -1; int flags = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, cast(void*)&flags, int.sizeof); setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, cast(void*)&flags, int.sizeof); if (bind(fd, cast(sockaddr*)&addr, addr.sizeof) == -1) { fd.close; return -1; } if (listen(fd, 4) == -1) { fd.close; return -1; } return fd; } extern (C) int main() { enum PORT = 4444; int listener = server(PORT); if (listener == -1) { fprintf(stderr, "Failed to init server : %d : %s\n", errno, strerror(errno)); return 1; } printf("Listening on %d.\n", PORT); sockaddr_storage addr; socklen_t addrlen = addr.sizeof; char[NI_MAXHOST] hoststr; char[NI_MAXSERV] portstr; ubyte[4096] buf; while (true) { int client = listener.accept(cast(sockaddr*)&addr, &addrlen); if (client < 0) { fprintf(stderr, "Failed to accept socket : %d : %s\n", errno, strerror(errno)); listener.close; return 1; } getnameinfo(cast(sockaddr*)&addr, addrlen, hoststr.ptr, hoststr.sizeof, portstr.ptr, portstr.sizeof, NI_NUMERICHOST | NI_NUMERICSERV); printf("Received connection from %s:%s.\n", hoststr.ptr, portstr.ptr); while (true) { ptrdiff_t len = client.recv(cast(void*)&buf, buf.sizeof, 0); if (len <= 0) break; if (client.send(cast(void*)&buf, len, 0) < 0) break; } client.close; printf("Lost connection from %s:%s.\n", hoststr.ptr, portstr.ptr); } }
This server is basically identical to echo serial, except that it only uses libc for networking, and it can be compiled with -betterC. Fun fact: this version compiles in 6%-10% of the time of the other version.