c - 套接字代码拒绝 Pi 上的本地主机连接,而不是 Linux?

标签 c linux sockets raspberry-pi

我遇到了有关 c 套接字系统的问题。我的代码很简单,它在端口 5800 上的本地主机上打开一个套接字并写入一个 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“nc -l localhost 5800”),没有输出产生。

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

我的问题是,哪些因素可能导致我的程序在树莓派上失败,我应该如何解决这些问题?帮助将不胜感激。

编辑:树莓派上的端口 5800 未被阻止。我可以在本地主机 5800 上成功地将 netcat 服务器和客户端连接在一起。我的问题是,我的代码连接到我的 Linux PC 上的 netcat 服务器,而不是 pi 上的 netcat 服务器。

最佳答案

您的客户端指向本地主机,如果您指向本地主机,您将如何连接到另一台设备?

至于Connection Refused 输出,您应该检查是否有防火墙 以及您是否在同一网络上... (如果您没有连接到本地主机上的监听端口,而您正在尝试连接到另一台设备)。

但是你说你正在连接到本地主机上的 netcat 服务器,你应该检查 netcat 是否被正确使用......你为什么不发布详细 -v 的输出?

C 语言(UNIX 网络实现)上编写套接字客户端 时,您需要以下库... sys/socket.h 用于socketconnectsendrecv关闭功能。

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

netdb.h 用于addrinfo 结构(您应该使用它而不是 sockaddr_in,因为它总体上更易于使用,而且它的 IP 版本不可知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;
}

关于c - 套接字代码拒绝 Pi 上的本地主机连接,而不是 Linux?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48798902/

相关文章:

java - Java 客户端和 Python 服务器之间的 Socket 消息传递

C 套接字 - 并非所有套接字都在 select() 中接收

java - 在 Eclipse 中集成 SWIG

linux - NixOps:如何部署到现有的 NixOS VM?

linux - POSIX 或 Linux 获取 shell 进程唯一 ID 的方法

c++ - 如何在 C/C++ 中关闭特定客户端的套接字?

c - Termios 和打开文件

计数位设置到 32 位类型的给定位置

c - 我需要检查输入是否是 IF 语句中的数字

c - "dynamic tag"是什么意思本文中提到的: