我遇到有关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服务器成功通信的代码图像:
程序将预期的字符串发送到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服务器。
答案 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;
}