套接字代码拒绝Pi上的localhost连接,而不是Linux上的?

时间:2018-02-15 01:39:46

标签: c linux sockets raspberry-pi

我遇到有关c套接字系统的问题。我的代码很简单,它在端口5800上的localhost上打开一个套接字并写入一个5个字母的字符串。但是,此代码适用于Linux PC(Linux Lite),但在pi上失败,我也在Raspberry PI上使用Raspian操作系统。

我在两个编译器中使用g ++,没有编译器选项

我的最小例子如下:

#include <assert.h>
#include <iostream>
#include <string>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char** argv)
{   
    /*
    Initialize the socket connection
    */
    const int port = 5800;
    const char* ip = "127.0.0.1";   

    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (-1 == sock) {
        perror("socket() failed");
        assert(0 && "socket() failed");
    }

    struct sockaddr_in name;
    memset(&name, 0, sizeof(name));
    name.sin_family = AF_INET;
    name.sin_port = htons(port);
    inet_pton(AF_INET, ip, &(name.sin_addr));

    if (-1 == connect(sock, (sockaddr*)&name, sizeof(name))) {
        perror("connecting stream socket"); 
        assert(0 && "connect() failed");
    }

    write(sock, "Hello", 6);
    return 0;
}

所有这一切都很好,花花公子。编译没有任何问题。在Linux上,一切都在游泳。以下是与netcat服务器成功通信的代码图像:

Socket program successfully talking to a netcat server

程序将预期的字符串发送到netcat。但是,在新的pi上编译此代码并在上述相同的场景中运行它会导致以下终端输出:

在客户端:

connecting stream socket: Connection refused
build: vid.cpp:61: int main(int, char**): Assertation \`0 && connect() 
failed.
Aborted 

在服务器端(netcat&#34; nc -l localhost 5800&#34;),不会产生任何输出。

我正在使用的端口正常工作。 (我用netcat测试过)pi上没有其他设置不同,源代码在pi和Linux机器上完全相同。 PI是新鲜的,没有任何设置改变。

我的问题是,哪些因素可能导致我的程序在树莓派上失败,我可以做些什么来解决它们?帮助将不胜感激。

编辑:树莓派上没有阻止端口5800。我可以在localhost 5800上成功连接netcat服务器和客户端。我的问题是,我的代码连接到我的Linux PC上的netcat服务器,而不是pi上的netcat服务器。

1 个答案:

答案 0 :(得分:0)

您的客户端指向localhost ,如果您指向localhost,如何连接到其他设备?

对于连接拒绝输出,您应检查是否有防火墙,如果您在同一网络,还应 ... (如果您没有连接到localhost上的持久端口,并且 尝试连接到其他设备 )。

但是你说你要连接到localhost上的netcat服务器,你应该检查netcat是否使用得很好...为什么不发布详细-v的输出?

C 语言( UNIX 网络实施)上编写套接字客户端时,需要以下库... 套接字 sys / socket.h 连接发送 recv 关闭功能。

您正在 sockaddr_in 使用 netinet / in.h arpa / inet.h ,此结构用于定义地址套接字...此外,此结构是旧UNIX网络实现的一部分。

addrinfo 结构的 netdb.h (您应该使用它而不是sockaddr_in,因为它总体上更易于使用,并且其IP版本无关< / em>, sockaddr_in 在IPv4中运行,据说,使用addrinfo是您应该使用的较新实现的一部分,因为它在IPv4和IPv6中都有效)...

另外......你正在使用write(),这很好,因为你正在写入文件描述符(在这种情况下是套接字),但send()函数会更加合适。

这是我的客户端实现...我在Android上使用它作为已编译的二进制文件和我的Archlinux x86_64 PC。

#include <netdb.h>
#include <sys/socket.h>
#include <string.h> // for memset()

#define PORT "1234"
#define IP "127.0.0.1"

int main(void)
{
    int sockfd;
    struct addrinfo hints, *res;

    memset(&hints, 0, sizeof(hints));

    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = 0;

    getaddrinfo(IP, PORT, &hints, &res);

    sockfd = socket(res->ai_family, res->ai_socktype, res->ai_flags);

    connect(sockfd, res->ai_addr, res->ai_addrlen);

    close(sockfd);

    return 0;
}

下一个是我的服务器实施。

#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>

#define PORT "7654"

int main(void){
    int sockfd, newsockfd;
    struct addrinfo hints, *res;

    memset(&hints, 0, sizeof(struct addrinfo));

    hints.ai_family   = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags    = AI_PASSIVE;

    getaddrinfo(NULL, PORT, &hints, &res);

    sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);

    bind(sockfd, res->ai_addr, res->ai_addrlen);
    freeaddrinfo(res);
    listen(sockfd, 1);

    struct sockaddr_in c_addr;
    socklen_t c_addrlen = sizeof(c_addr);

    newsockfd = accept(sockfd, (struct sockaddr *) &c_addr, &c_addrlen);

    close(newsockfd);
    close(sockfd);

    return 0;
}