【问题标题】:Trying to establish an internal connection with sockets between threads and connect fails尝试在线程之间建立与套接字的内部连接并连接失败
【发布时间】:2013-05-26 17:32:57
【问题描述】:

我正在尝试使用 AF_INET 系列的套接字在同一进程的线程之间创建本地连接。
服务器应该通过与线程的多路复用来处理客户端并服务他们的请求。

所以在服务器的主线程我有这个用于外部连接: (为了保持帖子的长度合理,省略了检查错误)

struct sockaddr_in server_addr;
struct sockaddr *serverptr=(struct sockaddr *)&server_addr;
listening_sock = socket(AF_INET, SOCK_STREAM, 0);
fds[0].fd = listening_sock;
fds[0].events = POLLIN;
// Setting listening socket
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
int one = 1;
setsockopt(listening_sock, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one));
setsockopt(listening_sock, IPPROTO_TCP, TCP_NODELAY, (void *)&one, sizeof(one));
bind(listening_sock, serverptr, sizeof(server_addr));
listen(listening_sock, 5);

然后使用 poll 我在侦听套接字上成功轮询(与客户端通信)。

现在我想通过 TCP 创建一个内部套接字,用于主线程和我将创建的新线程之间的通信。
我已经添加了这些:

struct sockaddr_in loopback_addr;
struct sockaddr *loopbackptr=(struct sockaddr *)&loopback_addr;
loopback_sock = socket(AF_INET, SOCK_STREAM, 0); //checking for errors is omitted
fds[1].fd = loopback_sock;
fds[1].events = POLLIN;
// Setting loopback socket
loopback_addr.sin_addr.s_addr = htonl(IN_LOOPBACKNET);
loopback_addr.sin_family = AF_INET;
loopback_addr.sin_port = htons(18000);
int one = 1;
setsockopt(loopback_sock, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one));
setsockopt(loopback_sock, IPPROTO_TCP, TCP_NODELAY, (void *)&one, sizeof(one));
bind(loopback_sock, loopback_ptr, sizeof(loopback_addr));
listen(loopback_sock, 5);

并且还将 nfds 计数器增加到 2。
现在线程在 poll 循环之前启动并尝试与此代码进行通信:

struct sockaddr_in server;
struct sockaddr *serverptr = (struct sockaddr*)&server;
int sock;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
    perror("thread: socket");
    pthread_exit((void*)-1);
}

int port = 18000;
server.sin_family = AF_INET;      
server.sin_addr.s_addr = IN_LOOPBACKNET; 
server.sin_port = htons(port);        
if (connect(sock, serverptr, sizeof (server)) < 0)
{
    perror("thread: connect");
    pthread_exit((void*)-1);
}

然后发生的是 connect 系统调用返回 thread: connect: Network is unreachable

在服务器的主循环我有这个:

if (fd[1].revents)
    printf("Loopback socket\n");

检查此套接字是否有任何交互,但这从不打印任何内容。

我不知道如何设置内部套接字,如果有我可以阅读的教程,欢迎提供链接!

这可能很简单,但由于我是套接字编程的新手,所以我找不到它。


编辑:
按照 alk 的建议将 IN_LOOPBACKNET 更改为 htonl(INADDR_LOOPBACK) 后,连接仍然失败,但出现新消息 connection refused
但仍然没有来自 fds[2] 的回复。

【问题讨论】:

  • 服务器对bind()的调用不是报错了吗?
  • @alk:不,没有错误:/我发布的第二个代码块一定有问题。服务器可以很好地处理客户端的“外部”通信。但是从内部套接字获得连接被拒绝。

标签: c linux sockets polling multiplexing


【解决方案1】:

从错误消息 (Network is unreachable) 中,您可以得出结论,寻址存在问题。

所以你可能想改变

IN_LOOPBACKNET

成为

INADDR_LOOPBACK

前者解析为127,这很可能不是您想要的,因为它是本地环回网络。

后者更适合,因为它解析为0x7f000001,它是环回地址127.0.0.1 的整数表示。


在分配客户端应连接的 IP 地址时,您还缺少转换为网络字节顺序 (htonl())。

【讨论】:

  • 我试图找出发生了什么,我使用了 gethostbyname,因为我将它与我的客户端应用程序一起使用,将它作为参数“localhost”并且它有效,给了我一个 connection refused。现在,我已经用你发布的内容更新了代码,仍然得到connection refused,而服务器的主循环没有任何打印。
  • @Chris:您没有显示服务器源中确实等待连接进入的部分,但您知道需要调用accept() 来这样做,不是吗?你呢? Connection refused 只是告诉客户端没有人在等待accept() 在您尝试连接的地址:端口上的连接。
  • 是的,我知道我们需要接受。问题是服务器上本地主机的地址。如果您注意到,它是 IN_LOOPBACKNET,而它应该是 INADDR_LOOPBACK。感谢您的帮助!另外,请您回答我,通过网络发送的所有数字都应该用 htonl/s 转换吗?
  • @Chris: Yuo 可能还想展示涉及accept() 的代码。并且:您是否还更正了有关错误使用 IN_LOOPBACKNET 的服务器来源?
  • 是的,我做到了,它现在完美运行。我应该在这里更新我的代码吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-29
  • 1970-01-01
  • 1970-01-01
  • 2015-07-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多