Projektarbeit Line Following Robot bei Prof. Chowanetz im WS22/23
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lfr_socket.cpp 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. #include "lfr_socket.h"
  2. LFR_Socket::LFR_Socket(ExceptionCallback cb): cb(cb)
  3. {
  4. if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  5. {
  6. throw std::runtime_error("Failed opening the socket");
  7. }
  8. if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)) != 0)
  9. {
  10. throw std::runtime_error("Failed setting the socket options");
  11. }
  12. address.sin_family = AF_INET;
  13. address.sin_addr.s_addr = INADDR_ANY;
  14. address.sin_port = htons(8080);
  15. if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) != 0)
  16. {
  17. throw std::runtime_error("Failed binding a name to the socket");
  18. }
  19. if (listen(server_fd, 3) != 0)
  20. {
  21. throw std::runtime_error("Failed listening for connections");
  22. }
  23. }
  24. LFR_Socket::~LFR_Socket()
  25. {
  26. endLoop();
  27. thread->join();
  28. }
  29. void LFR_Socket::removeListener(LFR_Socket::ListenerKey key)
  30. {
  31. std::lock_guard<std::mutex> lock(mutex);
  32. auto it = std::find_if(std::begin(listeners), std::end(listeners), [&](auto const &val){
  33. return val.first == key;
  34. });
  35. if(it != std::end(listeners))
  36. {
  37. listeners.erase(it);
  38. }
  39. }
  40. void LFR_Socket::addListener(LFR_Socket::ListenerCallback cb, LFR_Socket::ListenerKey key)
  41. {
  42. std::lock_guard<std::mutex> lock(mutex);
  43. listeners.emplace_back(key, std::move(cb));
  44. }
  45. void LFR_Socket::setStop(bool val)
  46. {
  47. std::lock_guard<std::mutex> lock(mutex);
  48. stop = val;
  49. }
  50. void LFR_Socket::createThread()
  51. {
  52. thread = std::make_unique<std::thread>([this](){
  53. bool connected = false;
  54. while(true)
  55. {
  56. LFR_Socket::LFR_Telegram telegram;
  57. bool received = false;
  58. if(!stop && !listeners.empty())
  59. {
  60. try
  61. {
  62. std::lock_guard<std::mutex> lock(mutex);
  63. struct pollfd pollfds[2];
  64. pollfds[0].fd = server_fd;
  65. pollfds[0].events = POLLIN;
  66. pollfds[1].events = POLLIN;
  67. if (poll(pollfds, 2, 200) > 0)
  68. {
  69. if(pollfds[0].revents & POLLIN || pollfds[1].revents & POLLIN)
  70. {
  71. if (!connected && pollfds[0].revents & POLLIN)
  72. {
  73. if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) == -1)
  74. {
  75. throw std::runtime_error("failed accepting connection");
  76. }
  77. else
  78. {
  79. pollfds[1].fd = new_socket;
  80. connected = true;
  81. }
  82. }
  83. else if (pollfds[1].revents & POLLIN)
  84. {
  85. bytes_received = recv(new_socket, buffer, sizeof(buffer), 0);
  86. if (bytes_received > 0)
  87. {
  88. received = true;
  89. std::copy(std::begin(buffer), std::end(buffer), std::begin(telegram));
  90. }
  91. }
  92. }
  93. }
  94. }
  95. catch(std::exception const &ex)
  96. {
  97. if(!cb(ex))
  98. {
  99. //callback returned false -> exception not handled -> exit
  100. exit(EXIT_FAILURE);
  101. }
  102. }
  103. //Invoke the callback method (ListenerPair second -> ListenerCallback)
  104. if (received)
  105. {
  106. for(auto &val : listeners)
  107. {
  108. val.second(telegram);
  109. }
  110. }
  111. }
  112. else
  113. {
  114. break;
  115. }
  116. std::this_thread::sleep_for(std::chrono::milliseconds(150));
  117. }
  118. });
  119. }
  120. void LFR_Socket::startLoop()
  121. {
  122. if(thread)
  123. {
  124. //Restart thread if it is running
  125. setStop(true);
  126. thread->join();
  127. setStop(false);
  128. }
  129. createThread();
  130. }
  131. void LFR_Socket::endLoop()
  132. {
  133. setStop(true);
  134. }
  135. int main()
  136. {
  137. std::mutex mutex;
  138. LFR_Socket socket([&](std::exception const &ex)
  139. {
  140. std::unique_lock<std::mutex> lock(mutex);
  141. std::cerr<<"socket exception:"<<ex.what()<<std::endl;
  142. return false;
  143. });
  144. socket.addListener([&](LFR_Socket::LFR_Telegram telegram)
  145. {
  146. std::unique_lock<std::mutex> lock(mutex);
  147. std::cout << telegram;
  148. }, &mutex);
  149. socket.startLoop();
  150. //send(new_socket, "Hello from the server", sizeof("Hello from the server"), 0);
  151. char input;
  152. std::cout << "press q to quit" << std::endl;
  153. std::cin >> input;
  154. std::cout << "cinned" << std::endl;
  155. while (input != 'q')
  156. {
  157. std::cin >> input;
  158. std::cout << "cinned" << std::endl;
  159. }
  160. std::cout << "im out" << std::endl;
  161. return 0;
  162. }