// // Created by casic on 25-2-25. // #include "tcp_service.hpp" #include <iomanip> #include <cerrno> #include <vector> #include <iostream> #include <stdexcept> #include <cstring> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> void TcpService::init_serial_port(const std::string &port_name, const int baud_rate) { _port.open(port_name); if (_port.is_open()) { _port.set_option(serial_port_base::baud_rate(baud_rate)); _port.set_option(serial_port_base::character_size(8)); _port.set_option(serial_port_base::stop_bits(serial_port_base::stop_bits::one)); _port.set_option(serial_port_base::parity(serial_port_base::parity::none)); _port.set_option(serial_port_base::flow_control(serial_port_base::flow_control::none)); } else { std::cerr << "Failed to open serial port" << std::endl; } } TcpService::TcpService( boost::asio::io_context &io_context, const std::string &port_name, const int baud_rate ): _context(io_context), _port(io_context) { std::cout << "TcpService::init success" << std::endl; init_serial_port(port_name, baud_rate); } void TcpService::handle_data_packet(std::vector<uint8_t> &data) { for (const uint8_t i: data) { std::cout << std::hex << std::uppercase << std::setw(2) << std::setfill('0') << static_cast<int>(static_cast<uint8_t>(i)) << " "; } std::cout << std::endl; //转为std::vector<uint8_t>并发给机械臂串口 std::vector command(data.begin(), data.end()); const size_t bytes_to_send = command.size(); if (bytes_to_send == 0) { std::cout << "Empty command, nothing to send." << std::endl; return; } try { const size_t bytes_sent = boost::asio::write(_port, boost::asio::buffer(command)); if (bytes_sent == bytes_to_send) { std::cout << "sent successfully" << std::endl; } else { std::cerr << "only " << bytes_sent << " bytes sent out of " << bytes_to_send << std::endl; } } catch (const boost::system::system_error &e) { std::cerr << "error sending data: " << e.what() << std::endl; } } void TcpService::handle_client(const int client_socket) { std::vector<uint8_t> buffer; char byte; while (true) { const ssize_t bytes_received = recv(client_socket, &byte, 1, 0); if (bytes_received < 0) { std::cerr << "Failed to receive data: " << strerror(errno) << std::endl; close(client_socket); return; } if (bytes_received == 0) { std::cerr << "Connection closed by client" << std::endl; close(client_socket); return; } buffer.push_back(byte); if (static_cast<uint8_t>(byte) == 0xFA) { // 处理接收到的数据包 if (!buffer.empty()) { handle_data_packet(buffer); buffer.clear(); // 清空缓冲区以接收下一个数据包 } } } } void TcpService::start(const int port) { try { _socket_fd = socket(AF_INET, SOCK_STREAM, 0); if (_socket_fd == -1) { throw std::runtime_error("failed to create socket"); } // 绑定套接字 sockaddr_in server_addr = {}; server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(port); if (bind(_socket_fd, reinterpret_cast<sockaddr *>(&server_addr), sizeof(server_addr)) == -1) { throw std::runtime_error("failed to bind socket"); } // 监听连接,最多允许5个连接 if (listen(_socket_fd, 5) == -1) { throw std::runtime_error("failed to listen on socket"); } std::cout << "TcpService started" << " and listening on port " << port << std::endl; // 接受连接 while (true) { sockaddr_in client_addr{}; socklen_t client_len = sizeof(client_addr); const int client_socket_fd = accept(_socket_fd, reinterpret_cast<sockaddr *>(&client_addr), &client_len); if (client_socket_fd == -1) { std::cerr << "failed to accept connection" << std::endl; continue; } std::cout << "accepted connection from " << inet_ntoa(client_addr.sin_addr) << ":" << ntohs(client_addr.sin_port) << std::endl; // 处理连接 handle_client(client_socket_fd); } } catch (const std::exception &e) { std::cerr << "exception in tcp_server::start: " << e.what() << std::endl; } }