TCPServerUtility.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. #include <netdb.h>
  2. #include <sys/socket.h>
  3. #include <sys/types.h>
  4. #include <unistd.h>
  5. #include "Practical.h"
  6. static const int MAX_PENDING = 5;
  7. int setup_tcp_server_socket(const char *service) {
  8. struct addrinfo addr_criteria = { 0 };
  9. addr_criteria.ai_family = AF_UNSPEC;
  10. addr_criteria.ai_flags = AI_PASSIVE;
  11. addr_criteria.ai_socktype = SOCK_STREAM;
  12. addr_criteria.ai_protocol = proto_get_num("tcp");
  13. struct addrinfo *serv_addr = nullptr;
  14. int ret = getaddrinfo(nullptr, service, &addr_criteria, &serv_addr);
  15. if (ret != 0) {
  16. DieWithUserMessage("getaddrinfo() failed", gai_strerror(ret));
  17. }
  18. int serv_sock = -1;
  19. for (struct addrinfo *addr = serv_addr; addr != nullptr; addr = addr->ai_next) {
  20. serv_sock = socket(AF_to_PF(addr->ai_family), addr->ai_socktype, addr->ai_protocol);
  21. if (serv_sock < 0) {
  22. continue;
  23. }
  24. if (
  25. (bind(serv_sock, addr->ai_addr, addr->ai_addrlen) == 0)
  26. && (listen(serv_sock, MAX_PENDING) == 0)
  27. ) {
  28. struct sockaddr_storage local_addr;
  29. socklen_t addr_size = sizeof(local_addr);
  30. if (getsockname(serv_sock, (struct sockaddr *) &local_addr, &addr_size) < 0) {
  31. DieWithSystemMessage("getsockname() failed");
  32. }
  33. fputs("Binding to: ", stdout);
  34. PrintSocketAddress((struct sockaddr *) &local_addr, stdout);
  35. fputc('\n', stdout);
  36. break;
  37. } else {
  38. close(serv_sock);
  39. serv_sock = -1;
  40. }
  41. }
  42. freeaddrinfo(serv_addr);
  43. return serv_sock;
  44. }
  45. int accept_tcp_connection(const int serv_sock) {
  46. struct sockaddr_storage client_addr;
  47. socklen_t client_addr_len = sizeof(client_addr);
  48. int client_sock = accept(serv_sock, (struct sockaddr *) &client_addr, &client_addr_len);
  49. if (client_sock < 0) {
  50. DieWithSystemMessage("accept() failed");
  51. }
  52. fputs("Handling client ", stdout);
  53. PrintSocketAddress((struct sockaddr *) &client_addr, stdout);
  54. fputc('\n', stdout);
  55. return client_sock;
  56. }
  57. void HandleTCPClient(const int client_sock) {
  58. char buffer[BUFSIZE];
  59. ssize_t num_bytes_rcvd = recv(client_sock, buffer, BUFSIZE, 0);
  60. if (num_bytes_rcvd < 0) {
  61. DieWithSystemMessage("recv() failed");
  62. }
  63. while (num_bytes_rcvd > 0) {
  64. ssize_t num_bytes_sent = send(client_sock, buffer, num_bytes_rcvd, 0);
  65. if (num_bytes_sent < 0) {
  66. DieWithSystemMessage("send() failed");
  67. } else if (num_bytes_sent != num_bytes_rcvd) {
  68. DieWithUserMessage("send()", "sent unexpected number of bytes");
  69. }
  70. num_bytes_rcvd = recv(client_sock, buffer, BUFSIZE, 0);
  71. if (num_bytes_rcvd < 0) {
  72. DieWithSystemMessage("recv() failed");
  73. }
  74. }
  75. close(client_sock);
  76. }