我对套接字和任何类型的网络编程都是99%的新手,所以请多多包涵。
我的目标是连接到本地计算机(192.168.0.1)上的端口(在这种情况下为2111)。从那里开始,我正计划发送和接收基本信息,但是那是另一天。
我目前已经尝试过:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char **argv)
{
int sd;
int port;
int start;
int end;
int rval;
struct hostent *hostaddr;
struct sockaddr_in servaddr;
start = 2111;
end = 2112;
for(port = start; port <= end; port++)
{
sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sd == -1)
{
perror("Socket()\n");
return (errno);
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(port);
hostaddr = gethostbyname("192.168.0.1");
memcpy(&servaddr.sin_addr, hostaddr->h_addr, hostaddr->h_length);
rval = connect(sd, (struct sockaddr *)&servaddr, sizeof(servaddr));
if(rval == -1)
{
printf("Port %d is closed\n", port);
close(sd);
}
else printf("Port %d is open\n", port);
close(sd);
}
return 0;
}
但是,我的connect()
电话挂了大约90秒,然后返回-1。
该设备直接连接到Mac Mini的以太网端口,制造商已确认该端口为2111或2112。
我究竟做错了什么?另外,它可以采用ELI5(就像我5岁时那样解释)格式吗?我举几个例子要好得多。
当您呼叫connect()
连接到主机时,您的计算机将发送一个SYN数据包,以开始TCP连接的三向握手。从这里开始,有3种可能的情况:
connect()
成功返回。connect()
呼叫几乎立即失败并出现错误ECONNREFUSED
(连接被拒绝)。在正常情况下,这需要1个网络往返时间(RTT),通常为数十或数百毫秒。connect()
调用失败,并显示ETIMEDOUT
。这通常是1-2分钟,具体取决于操作系统及其TCP设置。您显然正在处理案例3。这可能是由几个不同的问题引起的:
如果直接通过以太网连接到设备,则排除#1和#2。#4是可能的,但我认为#3是最可能的解释。
您的计算机具有多个网络接口-以太网(有时为多个以太网接口),Wi-Fi,环回设备,VPN隧道等。无论何时创建套接字,都必须将其绑定到一个或多个特定的网络接口,以便OS知道实际通过哪个NIC发送数据包。对于服务器的侦听套接字,通常绑定到所有网络接口(侦听所有接口),但是也可以绑定到特定的网络接口以仅侦听该接口。
对于客户端套接字,将它们连接到其他对等端时,通常不会将它们绑定到特定接口。默认情况下,您的计算机使用其内部路由表以及目标IP地址来确定要使用的网络接口。例如,如果您有一台具有两个NIC的网关计算机,其中一个通过IP 54.xyz连接到公共互联网,而另一个通过IP 192.168.1.1连接到内部专用网络,则该计算机将路由表极有可能说“对于发往192.168.0.0/16的数据包,使用NIC 2,对于所有其他数据包,使用NIC 1”。如果要绕过路由表,可以通过在调用bind()
之前在套接字上进行调用来将套接字绑定到所需的网络接口connect()
。
那么,这对您意味着什么?
首先,确保192.168.0.1实际上是您应该连接的正确目标地址。该地址如何确定?您的计算机是否充当DHCP服务器,以将该地址分配给其他主机?该主机是否使用静态IP配置?
接下来,确保您的路由表正确。如果另一台计算机为其自身分配了静态IP,则很可能是您的Mac不知道如何路由到该目的地,并且可能正在尝试通过错误的接口进行路由。您可以使用route(8)
实用程序在Mac OS X上手动调整路由,但是每次重新启动时都会重置这些路由;该博客文章显示了一个示例,该示例使用启动项在启动时自动添加新路线。您将要使用与连接到目标主机的以太网接口关联的IP地址。
另外,也可以不使用路由表,而可以bind()
在connect()
绑定到要使用的接口的本地地址之前调用套接字,但这不适用于其他程序,除非它们也提供了该功能。例如,该curl(1)
实用程序使您可以传递--interface <name>
命令行标志来将其定向以绑定到特定接口。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句