tcp_msg_peek.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #include <arpa/inet.h>
  2. #include <errno.h>
  3. #include <fcntl.h>
  4. #include <netinet/in.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <sys/socket.h>
  9. #include <sys/stat.h>
  10. #include <sys/types.h>
  11. #include <sys/wait.h>
  12. #include <unistd.h>
  13. #define SRV_IP "127.0.0.1"
  14. #define PORT 11111
  15. #define BUFLEN 512
  16. enum { SINGLE, PARALLEL } mode = PARALLEL;
  17. int pipefds[2];
  18. void server(void) {
  19. int listening_socket, client_socket;
  20. struct sockaddr_in address;
  21. socklen_t addrlen;
  22. if ((listening_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  23. perror("socket");
  24. exit(1);
  25. }
  26. int enable = 1;
  27. if (setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) < 0) {
  28. perror("setsockopt");
  29. exit(1);
  30. }
  31. memset(&address, 0, sizeof(address));
  32. address.sin_family = AF_INET;
  33. address.sin_port = htons(PORT);
  34. address.sin_addr.s_addr = htonl(INADDR_ANY);
  35. if (bind(listening_socket, (struct sockaddr*)&address, sizeof(address)) < 0) {
  36. perror("bind");
  37. exit(1);
  38. }
  39. if (listen(listening_socket, 3) < 0) {
  40. perror("listen");
  41. exit(1);
  42. }
  43. if (mode == PARALLEL) {
  44. if (close(pipefds[0]) < 0) {
  45. perror("close of pipe");
  46. exit(1);
  47. }
  48. char byte = 0;
  49. ssize_t written = 0;
  50. while (written == 0) {
  51. if ((written = write(pipefds[1], &byte, sizeof(byte))) < 0) {
  52. if (errno == EINTR || errno == EAGAIN)
  53. continue;
  54. perror("write on pipe");
  55. exit(1);
  56. }
  57. }
  58. }
  59. addrlen = sizeof(address);
  60. client_socket = accept(listening_socket, (struct sockaddr*)&address, &addrlen);
  61. if (client_socket < 0) {
  62. perror("accept");
  63. exit(1);
  64. }
  65. if (close(listening_socket) < 0) {
  66. perror("close of listening socket");
  67. exit(1);
  68. }
  69. puts("[server] client is connected...");
  70. char buffer[] = "Hello from server!\n";
  71. ssize_t written = 0;
  72. while (written < sizeof(buffer)) {
  73. ssize_t n;
  74. if ((n = sendto(client_socket, buffer + written, sizeof(buffer) - written, 0, 0, 0)) < 0) {
  75. if (errno == EINTR || errno == EAGAIN)
  76. continue;
  77. perror("sendto to client");
  78. exit(1);
  79. }
  80. written += n;
  81. }
  82. if (close(client_socket) < 0) {
  83. perror("close of client socket");
  84. exit(1);
  85. }
  86. puts("[server] done");
  87. }
  88. static ssize_t client_recv(int server_socket, char* buf, size_t len, int flags) {
  89. ssize_t read = 0;
  90. while (1) {
  91. ssize_t n;
  92. if ((n = recv(server_socket, buf + read, len - read, flags)) < 0) {
  93. if (errno == EINTR || errno == EAGAIN)
  94. continue;
  95. perror("client recv");
  96. exit(1);
  97. }
  98. read += n;
  99. if (!n || flags & MSG_PEEK) {
  100. /* recv with MSG_PEEK flag should be done only once */
  101. break;
  102. }
  103. }
  104. return read;
  105. }
  106. void client(void) {
  107. int server_socket;
  108. struct sockaddr_in address;
  109. char buffer[BUFLEN];
  110. ssize_t count;
  111. if (mode == PARALLEL) {
  112. if (close(pipefds[1]) < 0) {
  113. perror("close of pipe");
  114. exit(1);
  115. }
  116. char byte = 0;
  117. ssize_t received = 0;
  118. while (received == 0) {
  119. if ((received = read(pipefds[0], &byte, sizeof(byte))) < 0) {
  120. if (errno == EINTR || errno == EAGAIN)
  121. continue;
  122. perror("read on pipe");
  123. exit(1);
  124. }
  125. }
  126. }
  127. if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  128. perror("socket");
  129. exit(1);
  130. }
  131. memset(&address, 0, sizeof(address));
  132. address.sin_family = AF_INET;
  133. address.sin_port = htons((PORT));
  134. if (inet_aton(SRV_IP, &address.sin_addr) == 0) {
  135. perror("inet_aton");
  136. exit(1);
  137. }
  138. if (connect(server_socket, (struct sockaddr*)&address, sizeof(address)) < 0) {
  139. perror("connect");
  140. exit(1);
  141. }
  142. printf("[client] receiving with MSG_PEEK: ");
  143. count = client_recv(server_socket, buffer, sizeof(buffer), MSG_PEEK);
  144. fwrite(buffer, count, 1, stdout);
  145. printf("[client] receiving without MSG_PEEK: ");
  146. count = client_recv(server_socket, buffer, sizeof(buffer), 0);
  147. fwrite(buffer, count, 1, stdout);
  148. printf("[client] checking how many bytes are left unread: ");
  149. count = client_recv(server_socket, buffer, sizeof(buffer), 0);
  150. printf("%zu\n", count);
  151. if (close(server_socket) < 0) {
  152. perror("close of server socket");
  153. exit(1);
  154. }
  155. puts("[client] done");
  156. }
  157. int main(int argc, char** argv) {
  158. if (argc > 1) {
  159. if (strcmp(argv[1], "client") == 0) {
  160. mode = SINGLE;
  161. client();
  162. return 0;
  163. }
  164. if (strcmp(argv[1], "server") == 0) {
  165. mode = SINGLE;
  166. server();
  167. return 0;
  168. }
  169. } else {
  170. pipe(pipefds);
  171. int pid = fork();
  172. if (pid == 0) {
  173. client();
  174. } else {
  175. server();
  176. }
  177. }
  178. return 0;
  179. }