UDPEchoClient.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. #include <sys/socket.h>
  2. #include <netdb.h>
  3. #include <stdio.h>
  4. #include <unistd.h>
  5. #include "Practical.h"
  6. #include "ch4_common.h"
  7. int main(int argc, char **argv) {
  8. if (argc < 3 || argc > 4) {
  9. DieWithUserMessage("Parameter(s)", "<Server Address/Name> <Echo Word> [<Server Port/Service>]");
  10. }
  11. char *server = argv[1];
  12. char *echo_str = argv[2];
  13. const size_t echo_str_len = sizeof(echo_str);
  14. if (echo_str_len > MAXSTRINGLENGTH) {
  15. DieWithUserMessage(echo_str, "string too long");
  16. }
  17. char *server_port = (argc == 4) ? argv[3] : "echo";
  18. struct addrinfo addr_criteria = { 0 };
  19. addr_criteria.ai_family = AF_UNSPEC;
  20. addr_criteria.ai_socktype = SOCK_DGRAM;
  21. addr_criteria.ai_protocol = proto_get_num("udp");
  22. struct addrinfo *serv_addr = nullptr;
  23. int ret = getaddrinfo(server, server_port, &addr_criteria, &serv_addr);
  24. if (ret != 0) {
  25. DieWithUserMessage("getaddrinfo() failed", gai_strerror(ret));
  26. }
  27. int sock = socket(
  28. serv_addr->ai_family,
  29. serv_addr->ai_socktype,
  30. serv_addr->ai_protocol
  31. );
  32. if (sock < 0) {
  33. DieWithSystemMessage("socket() failed");
  34. }
  35. fputs("Sending to ", stdout);
  36. PrintSocketAddress(serv_addr->ai_addr, stdout);
  37. fputc('\n', stdout);
  38. ssize_t num_bytes = sendto(
  39. sock,
  40. echo_str,
  41. echo_str_len,
  42. 0,
  43. serv_addr->ai_addr,
  44. serv_addr->ai_addrlen
  45. );
  46. if (num_bytes < 0) {
  47. DieWithSystemMessage("sendto() failed");
  48. } else if (num_bytes != echo_str_len) {
  49. DieWithUserMessage("sendto() error", "sent unexpected amount of bytes");
  50. }
  51. struct sockaddr_storage from_addr;
  52. socklen_t from_addr_len = sizeof(from_addr);
  53. char buf[MAXSTRINGLENGTH + 1];
  54. num_bytes = recvfrom(
  55. sock,
  56. buf,
  57. MAXSTRINGLENGTH,
  58. 0,
  59. (struct sockaddr *) &from_addr,
  60. &from_addr_len
  61. );
  62. if (num_bytes < 0) {
  63. DieWithSystemMessage("recvfrom() failed");
  64. } else if (num_bytes != echo_str_len) {
  65. DieWithUserMessage("recvfrom() error", "received unexpected amount of bytes");
  66. }
  67. if (!sock_addrs_equal(serv_addr->ai_addr, (struct sockaddr *) &from_addr)) {
  68. fputs("serv_addr: ", stdout);
  69. PrintSocketAddress(serv_addr->ai_addr, stdout);
  70. fputs("\nfrom_addr: ", stdout);
  71. PrintSocketAddress((struct sockaddr *) &from_addr, stdout);
  72. fputc('\n', stdout);
  73. DieWithUserMessage("recvfrom()", "received a packet from unkown source");
  74. }
  75. freeaddrinfo(serv_addr);
  76. buf[echo_str_len] = '\0';
  77. printf("Received: %s\n", buf);
  78. close(sock);
  79. return 0;
  80. }