UDPEchoClient.c 2.7 KB

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