我遇到了有关 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 服务器成功通信的代码图像:
程序将预期的字符串发送到 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 用于socket、connect、send、recv 和关闭功能。
netinet/in.h 和 arpa/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/