【问题标题】:TCP sockets over wlanWLAN 上的 TCP 套接字
【发布时间】:2011-08-10 20:58:45
【问题描述】:

我有一个项目使用 TCP 套接字在服务器和客户端之间进行通信。到目前为止,我一直在一台计算机上执行此操作,因此我刚刚使用本地地址“127.0.0.1”作为绑定和连接到两侧的地址,并且工作正常。现在我有第二台计算机作为客户端,但我不知道如何相应地更改地址。它们通过未连接到 Internet 的网络连接。在代码看起来像这样之前 -

服务器 -

 struct addrinfo hints;
struct addrinfo *servinfo; //will point to the results

//store the connecting address and size
struct sockaddr_storage their_addr;
socklen_t their_addr_size;


memset(&hints, 0, sizeof hints); //make sure the struct is empty
hints.ai_family = AF_INET; //local address
hints.ai_socktype = SOCK_STREAM; //tcp
hints.ai_flags = AI_PASSIVE; //use local-host address

//get server info, put into servinfo
if ((status = getaddrinfo("127.0.0.1", port, &hints, &servinfo)) != 0) {
    fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
    return false;
}

//make socket
fd = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);
if (fd < 0) {
    printf("\nserver socket failure %m", errno);
    return false;
}

//allow reuse of port
int yes=1;
if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char*) &yes,sizeof(int)) == -1) {
    perror("setsockopt");
    return false;
}

//unlink and bind
unlink("127.0.0.1");
if(bind (fd, servinfo->ai_addr, servinfo->ai_addrlen) < 0) {
    printf("\nBind error %m", errno);
    return false;
}

客户 -

struct addrinfo hints;
struct addrinfo *servinfo; //will point to the results

memset(&hints, 0, sizeof hints); //make sure the struct is empty
hints.ai_family = AF_INET; //local address
hints.ai_socktype = SOCK_STREAM; //tcp
hints.ai_flags = AI_PASSIVE; //use local-host address

//get server info, put into servinfo
if ((status = getaddrinfo("127.0.0.1", port, &hints, &servinfo)) != 0) {
    fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
    return false;
}

//make socket
fd = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);
if (fd < 0) {
    printf("\nserver socket failure %m", errno);
    return false;
}

//connect
if(connect(fd, servinfo->ai_addr, servinfo->ai_addrlen) < 0) {
    printf("\nclient connection failure %m", errno);
    return false;
}

我知道这应该很简单,但我不知道如何更改 IP 以使其正常工作。我尝试在这些行的引号中设置服务器计算机的 IP 地址 - if ((status = getaddrinfo("127.0.0.1", 端口, &hints, &servinfo)) != 0) 和 取消链接(“127.0.0.1”);

然后将客户端代码中的地址更改为该行中客户端计算机的IP地址- if ((status = getaddrinfo("127.0.0.1", port, &hints, &servinfo)) != 0)

每当我这样做时,它都会告诉我连接被拒绝。我还尝试过相反的方法,将服务器的地址放在客户端的行中,将客户端的地址放在服务器的行中,以及其他一些尝试。在这一点上,我觉得我只是在猜测。那么有人可以帮助我了解如何将其从使用一台计算机的本地地址更改为连接两台计算机吗?任何帮助表示赞赏。

【问题讨论】:

  • IP 是什么?你能在他们之间ping通吗?你确定没有防火墙?
  • 服务器ip是192.168.2.4,客户端是192.168.43.16。不过,我还没有考虑过防火墙。顺便说一句,如果这很重要的话,我正在使用 ubuntu。

标签: tcp ip-address bsd sockets


【解决方案1】:

首先,unlink("127.0.0.1"); 在这里是完全错误的,不要那样做。

然后,您有两台计算机通过某个网络连接。两者都应该有 IP 地址。将127.0.0.1 替换为客户端和服务器中服务器 的IP 地址。服务器不必事先知道客户端的地址——它会从accept(2) 调用中获取该信息。客户端需要服务器的地址才能知道连接的位置。服务器需要自己的地址来调用bind(2)

【讨论】:

  • 那么客户端的ip地址对于客户端有什么用呢?什么都没有?
  • 在向服务器发送数据包时,它会被客户端内核用作地址。
  • 还可以查看 Per 的回答 - 你根本不需要 AI_PASSIVE
  • @Sterling:是的,您的客户端程序中不需要它。内核根据路由表中的内容确定要使用的接口,因此 99% 的客户端代码中您不需要指定客户端(源)IP 地址。
  • 接受这个作为最直接的答案。感谢大家的帮助。
【解决方案2】:

主要问题是您将 AI_PASSIVE 放入客户端代码中。 AI_PASSIVE 仅适用于服务器(这就是它的信号)。

同样在服务器端你应该首先不要调用 unlink。这仅适用于 AF_UNIX 套接字,而不适用于 AF_INET。其次,您不需要将“127.0.0.1”放在服务器端的 getaddrinfo 行中。最好使用 NULL 来绑定所有可用的地址。

如果您更改这些内容,我相信您的代码应该可以工作。但是,您实际上应该使用 ai_next 指针循环 getaddrinfo 结果并尝试使用成功的第一个结果连接到每个结果。

【讨论】:

  • 我已经相应地更改了代码。但现在它只是在我调用连接函数时挂起。为什么要这样做?
  • 很可能是防火墙。如果您等待的时间足够长,您可能会收到“连接超时”。您确定计算机可以相互通信吗?不使用客户端代码,而是使用 telnet 或 nc 尝试从客户端机器连接到服务器地址和端口。
  • 我的理解是防火墙不会影响局域网流量。有错吗?
【解决方案3】:

Connection Refused 通常意味着您的客户收到了RST 到他的SYN。这通常是由于您尝试连接的端口上的服务器上缺少侦听套接字引起的。

  1. 运行你的服务器
  2. 在 CLI 上,键入 netstat -ant。您是否在端口上看到处于 LISTEN 状态的条目?

类似:

tcp4       0      0  *.3689                 *.*                    LISTEN  

我打赌你没有,因此你的服务器监听套接字有问题。我也打赌你在这一行所做的改变:

if ((status = getaddrinfo("127.0.0.1", port, &hints, &servinfo)) != 0) {

不太对。尝试在服务器上将该 IP 更改为 0.0.0.0 以告诉它绑定到系统上的任何 IP。在客户端,该行应该有服务器的 IP 地址。您还应该删除服务器中的unlink() 调用;不必要。

如果你确实有一个监听套接字,那么你的盒子之间可能有防火墙或其他东西阻止了 SYN。尝试在两个系统的 CLI 上键入 service iptables stop

【讨论】:

  • 我做了 netstat -ant 并得到了这个 - tcp 0 0 127.0.0.1:631 0.0.0:* LISTEN tcp 1 0 192.168.43.16:48744 91.189.89.144:80 CLOSE_WAIT tcp6 0 0 : :1:631 :::* LISTEN 似乎服务器端正在监听,但它有本地地址而不是 wlan 的 ip。
  • 您在哪台服务器上运行了 netstat?来自 CLOSE_WAIT 行和您的评论回复:IP,看起来来自您的客户。如果您仍然认为您的侦听器绑定到 127.0.0.1,请确保服务器上的 servinfo 结构中的 IP 为 0.0.0.0
  • 是的,我在客户端运行它。我用“0.0.0.0”切换了NULL,但它没有改变任何东西。代码现在只是挂在连接调用上。
  • 监听套接字需要在服务器上确认,而不是客户端。回复:挂起 -- 你的服务器代码中的任何地方都有accept() 调用吗?
  • 是的,在我上面发布的代码之后,有一个监听调用,然后是一个接受调用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-28
  • 1970-01-01
  • 1970-01-01
  • 2011-08-31
  • 2023-03-21
相关资源
最近更新 更多