#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #define SRV_IP "127.0.0.1" #define PORT 11111 #define BUFLEN 512 enum { SINGLE, PARALLEL } mode = PARALLEL; int pipefds[2]; void server(void) { int listening_socket, client_socket; struct sockaddr_in address; socklen_t addrlen; if ((listening_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); exit(1); } int enable = 1; if (setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) < 0) { perror("setsockopt"); exit(1); } memset(&address, 0, sizeof(address)); address.sin_family = AF_INET; address.sin_port = htons(PORT); address.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(listening_socket, (struct sockaddr*)&address, sizeof(address)) < 0) { perror("bind"); exit(1); } if (listen(listening_socket, 3) < 0) { perror("listen"); exit(1); } if (mode == PARALLEL) { if (close(pipefds[0]) < 0) { perror("close of pipe"); exit(1); } char byte = 0; ssize_t written = 0; while (written == 0) { if ((written = write(pipefds[1], &byte, sizeof(byte))) < 0) { if (errno == EINTR || errno == EAGAIN) continue; perror("write on pipe"); exit(1); } } } addrlen = sizeof(address); client_socket = accept(listening_socket, (struct sockaddr*)&address, &addrlen); if (client_socket < 0) { perror("accept"); exit(1); } if (close(listening_socket) < 0) { perror("close of listening socket"); exit(1); } puts("[server] client is connected..."); char buffer[] = "Hello from server!\n"; ssize_t written = 0; while (written < sizeof(buffer)) { ssize_t n; if ((n = sendto(client_socket, buffer + written, sizeof(buffer) - written, 0, 0, 0)) < 0) { if (errno == EINTR || errno == EAGAIN) continue; perror("sendto to client"); exit(1); } written += n; } if (close(client_socket) < 0) { perror("close of client socket"); exit(1); } puts("[server] done"); } static ssize_t client_recv(int server_socket, char* buf, size_t len, int flags) { ssize_t read = 0; while (1) { ssize_t n; if ((n = recv(server_socket, buf + read, len - read, flags)) < 0) { if (errno == EINTR || errno == EAGAIN) continue; perror("client recv"); exit(1); } read += n; if (!n || flags & MSG_PEEK) { /* recv with MSG_PEEK flag should be done only once */ break; } } return read; } void client(void) { int server_socket; struct sockaddr_in address; char buffer[BUFLEN]; ssize_t count; if (mode == PARALLEL) { if (close(pipefds[1]) < 0) { perror("close of pipe"); exit(1); } char byte = 0; ssize_t received = 0; while (received == 0) { if ((received = read(pipefds[0], &byte, sizeof(byte))) < 0) { if (errno == EINTR || errno == EAGAIN) continue; perror("read on pipe"); exit(1); } } } if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); exit(1); } memset(&address, 0, sizeof(address)); address.sin_family = AF_INET; address.sin_port = htons((PORT)); if (inet_aton(SRV_IP, &address.sin_addr) == 0) { perror("inet_aton"); exit(1); } if (connect(server_socket, (struct sockaddr*)&address, sizeof(address)) < 0) { perror("connect"); exit(1); } printf("[client] receiving with MSG_PEEK: "); count = client_recv(server_socket, buffer, sizeof(buffer), MSG_PEEK); fwrite(buffer, count, 1, stdout); printf("[client] receiving without MSG_PEEK: "); count = client_recv(server_socket, buffer, sizeof(buffer), 0); fwrite(buffer, count, 1, stdout); printf("[client] checking how many bytes are left unread: "); count = client_recv(server_socket, buffer, sizeof(buffer), 0); printf("%zu\n", count); if (close(server_socket) < 0) { perror("close of server socket"); exit(1); } puts("[client] done"); } int main(int argc, char** argv) { if (argc > 1) { if (strcmp(argv[1], "client") == 0) { mode = SINGLE; client(); return 0; } if (strcmp(argv[1], "server") == 0) { mode = SINGLE; server(); return 0; } } else { if (pipe(pipefds) < 0) { perror("pipe error"); return 1; } int pid = fork(); if (pid == 0) { client(); } else { server(); } } return 0; }