Так что в настоящее время я пытаюсь общаться по TCP от черного запущенного Debian на Mac. Я хочу общаться с beaglebone на Mac и отправлять текстовые сообщения между ними. Мой код настроен так, что у меня есть основное соединение, где я передаю видео через порт 1000, используя соединение UDP, и это само по себе работает нормально, но я настроил базовое соединение TCP для отправки текста через порт 10001 в отдельном pthread, и при соединении между двумя устройствами это дает мне вывод
ERROR connecting -1 Connection refused 111
Где, если я распечатаю значения, это говорит
Port: 10001, name: 192.168.1.37
Что особенно интересно для меня, так это то, что я знаю, что IP-адрес правильный, потому что я могу транслировать видео, используя IP-адрес и порт 10000.
Общая настройка: у меня есть микроконтроллер beaglebone (в основном, Raspberry Pi), подключенный к маршрутизатору, и мой Mac подключен через Ethernet к тому же маршрутизатору. Я использую библиотеку "sys / socket.h"
Код TCPClient (сторона macbook)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
class TCPClient {
private:
int sockfd;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[512];
void createSocket() {
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("ERROR opening socket\n");
exit(0);
}
}
void createConnection() {
memcpy((char *)server->h_addr_list[0],
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
int er = connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
if (er < 0) {
printf("ERROR connecting %i %s\n", er, strerror(errno));
exit(0);
}
}
public:
TCPClient(int port, char* name) {
memset((char *) &serv_addr, 0, sizeof(serv_addr));
printf("Port: %i, name: %s\n", port, name);
serv_addr.sin_port = htons(port);
server = gethostbyname(name);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
serv_addr.sin_family = AF_INET;
createSocket();
createConnection();
}
~TCPClient() {
close(sockfd);
}
void transmitData(char data[]) {
int n = write(sockfd, data, strlen(data));
if (n < 0) {
printf("ERROR writing to socket\n");
exit(0);
}
}
char* receiveData() {
memset(buffer, 0, sizeof(buffer));
int n = read(sockfd, buffer, sizeof(buffer));
if (n < 0) {
printf("ERROR reading from socket\n");
exit(0);
}
return buffer;
}
};
Код TCPServer (микроконтроллер)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
class TCPServer {
private:
// struct for data
int sockfd, newsockfd;
socklen_t clilen;
char buffer[512];
struct sockaddr_in serv_addr, cli_addr;
public:
TCPServer(int port) {
// clear address structure
memset((char *) &serv_addr, 0, sizeof(serv_addr));
// setup the host_addr structure for use in bind call
// server byte order
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
// automatically be filled with current host's IP address
serv_addr.sin_addr.s_addr = INADDR_ANY;
// Create socket
// socket(int domain, int type, int protocol)
// i.e. IPV_4, TCP, default
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("ERROR opening socket\n");
exit(0);
}
// Create bind
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
printf("ERROR on binding\n");
exit(0);
}
// start listening
// This listen() call tells the socket to listen to the incoming connections.
// The listen() function places all incoming connection into a backlog queue
// until `() call accepts the connection.
// Here, we set the maximum size for the backlog queue to 5.
listen(sockfd, 5);
// The accept() call actually accepts an incoming connection
clilen = sizeof(cli_addr);
// This accept() function will write the connecting client's address info
// into the the address structure and the size of that structure is clilen.
// The accept() returns a new socket file descriptor for the accepted connection.
// So, the original socket file descriptor can continue to be used
// for accepting new connections while the new socker file descriptor is used for
// communicating with the connected client.
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
printf("Ending accept function\n");
if (newsockfd < 0) {
printf("ERROR on accept");
exit(0);
}
printf("server: got connection from %s port %d\n",
inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));
}
~TCPServer() {
close(newsockfd);
close(sockfd);
}
void createSocket() {
// create a socket
// socket(int domain, int type, int protocol)
// i.e. IPV_4, TCP, default
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("ERROR opening socket\n");
exit(0);
}
}
void transmitData(char data[]) {
// This send() function sends the 13 bytes of the string to the new socket
send(newsockfd, data, strlen(data), 0);
}
char* receiveData() {
memset(buffer, 0, sizeof(buffer));
int n = read(newsockfd, buffer, sizeof(buffer));
if (n < 0) {
printf("ERROR reading from socket\n");
exit(0);
}
return buffer;
}
};
А вот код, который я использовал для создания соединения; это часть, которая работает на моем настольном компьютере (получает соединение и отображает выходной код)
void* sensor_com(void* conn_data_void) {
struct conn *conn_data = (struct conn*)conn_data_void;
printf("printing from pthread\n");
printf("port: %d \n", (*conn_data).port);
TCPServer *sensor_com = new TCPServer(conn_data->port);
char *buf = (char*) malloc(sizeof(char)*256);
while(1) {
// receive data from ROV and translate json
char *buffer = (*sensor_com).receiveData();
std::string json(buffer);
picojson::value v;
std::string err = picojson::parse(v, json);
if (! err.empty()) {
std:cerr << err << std::endl;
}
// check if the type of the value is "object"
if (! v.is<picojson::object>()) {
std::cerr << "JSON is not an object" << std::endl;
exit(2);
}
std::map<std::string, string> data;
// obtain a const reference to the map, and print the contents
const picojson::value::object& obj = v.get<picojson::object>();
for (picojson::value::object::const_iterator i = obj.begin();
i != obj.end();
++i) {
data[i->first] = i->second.to_str();
}
cout << "accel_x of rov: " << data["accel_x"] << endl;
cout << "accel_y of rov: " << data["accel_y"] << endl;
cout << "accel_z of rov: " << data["accel_z"] << endl;
cout << "gyro_x of rov: " << data["gyro_x"] << endl;
cout << "gyro_y of rov: " << data["gyro_y"] << endl;
cout << "gyro_z of rov: " << data["gyro_z"] << endl;
}
free(buf);
return NULL;
}
А это часть на микроконтроллере / биглебоне
void * sensor_com (void * conn_data_void) {
struct conn *conn_data = (struct conn*)conn_data_void;
unsigned int port = (*conn_data).port;
printf("printing from pthread\n");
printf("port: %d \n", port);
// create TCP connection includeing socket and connection call
TCPClient *sensor_com = new TCPClient(conn_data->port, conn_data->host);
char* val;
// Data from MPU6050
struct sensor_data movement;
if (RUNNING_ON_BEAGLEBONE) {
initialize_i2c();
}
// send data to master forever
while (1) {
if (RUNNING_ON_BEAGLEBONE) {
// collect data from I2C_interface
get_data(&movement);
} else {
// get data here
movement.accel_x = 10;
movement.accel_y = 10;
movement.accel_z = 10;
movement.gyro_x = 10;
movement.gyro_y = 10;
movement.gyro_z = 10;
}
// Create json for data to be stored
string data = "{";
// Add accelleration data
data += "\"accel_x\": \"" + std::to_string(movement.accel_x) + "\",";
data += "\"accel_y\": \"" + std::to_string(movement.accel_y) + "\",";
data += "\"accel_z\": \"" + std::to_string(movement.accel_z) + "\",";
// Add gyroscopic dataa
data += "\"gyro_x\": \"" + std::to_string(movement.gyro_x) + "\",";
data += "\"gyro_y\": \"" + std::to_string(movement.gyro_y) + "\",";
data += "\"gyro_z\": \"" + std::to_string(movement.gyro_z) + "\"}";
// convert to char array
char *charData = new char [data.length()+1];
strcpy(charData, data.c_str());
(*sensor_com).transmitData(charData);
// delay for readability
sleep(2);
}
free(val);
return NULL;
}
Я прошу прощения за стену кода, хотя, честно говоря, я думаю, что проблема связана с промежуточной связью, поэтому я не знаю, будет ли это полезно. Код работает нормально, когда он находится на одной машине (проблема заключается только в обмене данными между машинами). Я также пытался использовать tcpdump, но я не могу понять, как использовать его для отправки пакетов на другой сервер, я начинаю думать, что это просто для прослушивания пакетов, в этом случае это не очень полезно.
Любое руководство будет с благодарностью, спасибо!