如何在两个设备之间与TCP通信时修复错误"连接被拒绝"



因此,我目前正在尝试通过Beaglebone Black跑步Debian到Mac通过TCP进行通信。我想从Beaglebone通信到Mac,并在两者之间发送短信。我的代码设置的方式是我有一个主要连接,我使用UDP连接在端口1000上流式传输视频,这本身可以正常运行,但是我已经设置了一个基本的TCP连接以通过端口发送文本10001在单独的pthread中,在两个设备之间连接时,它给了我输出

ERROR connecting -1 Connection refused 111

如果我打印出

的值
Port: 10001, name: 192.168.1.37

我特别有趣的是,我知道IP地址是正确的,因为我可以使用IP地址和端口10000流式视频。

总体设置是我有一个beaglebone微控制器(基本上是覆盆子PI(,直到路由器上,我的Mac通过以太网连接到同一路由器。我正在使用库" 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 socketn");
            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 %sn", er, strerror(errno));
            exit(0);
        }
    }
public:
    TCPClient(int port, char* name) {
        memset((char *) &serv_addr, 0, sizeof(serv_addr));
        printf("Port: %i, name: %sn", port, name);
        serv_addr.sin_port = htons(port);
        server = gethostbyname(name);
        if (server == NULL) {
            fprintf(stderr,"ERROR, no such hostn");
            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 socketn");
            exit(0);
        }
    }
    char* receiveData() {
        memset(buffer, 0, sizeof(buffer));
        int n = read(sockfd, buffer, sizeof(buffer));
        if (n < 0) {
            printf("ERROR reading from socketn");
            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 socketn");
            exit(0);
        }
        // Create bind
        if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
            printf("ERROR on bindingn");
            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 functionn");
        if (newsockfd < 0) {
            printf("ERROR on accept");
            exit(0);
        }
        printf("server: got connection from %s port %dn",
               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 socketn");
            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 socketn");
            exit(0);
        }
        return buffer;
    }
};

这是我用来创建连接的代码;这是在我的桌面计算机上运行的部分(接收连接并显示输出代码(

void* sensor_com(void* conn_data_void) {
    struct conn *conn_data = (struct conn*)conn_data_void;
    printf("printing from pthreadn");
    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;
}

这是微控制器/beaglebone上的部分

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 pthreadn");
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,但我不知道如何使用它将数据包发送到另一台服务器,我开始认为这只是为了收听数据包,在这种情况下,它并不是很有帮助。

任何指导都将不胜感激,谢谢!

所以我弄清楚了这个问题,这在很大程度上要感谢 @user4581301

我最终试图重建最简单的版本,我发现的是,我基于许多代码的原始来源是问题(我找不到链接,但这只是一个教程(。它独立地在两台机器上都可以使用,但是如果您尝试在两台机器之间发送数据,则无法使用(可能与Beaglebone上的Debian OS和我的笔记本电脑上的Mac OS之间的不同库有关,或者只是某些功能是折旧(。

我最终从本网站(http://man7.org/linux/man-pages/man3/getaddrinfo.3.html(重建了TCP连接,该网站使用了新技术,并且能够在平台上使用较新的技术工作。所以我想我不确定问题是什么,但是如果您有一个通信跨平台的问题,我建议您看看Man7链接。

感谢大家的帮助!

最新更新