我们正在尝试实施基于Moxa UC-7112-LX嵌入式计算机(uClinux OS)的软件。我们使用Cinteron MC52i GSM调制解调器(常规GPRS服务)和标准pppd连接到互联网。
在连接之后,一切似乎都很好。 Ping实用程序正常工作,我的程序中的Socket函数也正常工作。然而,经过一段时间后,ppp连接以一种非常特殊的方式破碎。这些是这种情况的症状:
connect()
和write()
函数没有返回错误,但是当涉及到read()
时,函数返回时errno设置为ECONNRESET
(连接由对等方重置) 。该程序使用标准套接字函数(TCP协议)ifconfig ppp0
)所以,我的情况是:链接是否足以维护DNS解析服务(UDP正在工作?)但不足以运行TCP连接并接收ping回声......
情况不会一直出现。有时系统可以正常工作几天而没有任何问题。只要出现问题,简单的重置就可以解决所有问题。
我知道我们使用的系统很奇特,这里描述的情况可能与某些错误的tcp堆栈或pppd实现有关。考虑到系统是由制造商预先配置的,我没有任何重建/更改操作系统固件的选项。
我仍然希望有人在任何类似Linux的系统上看到过类似的情况。有没有办法测试为什么DNS名称解析工作,而其他网络的东西没有?是否可以使用某些pppd设置删除此类连接状态?
修改
首先,我想解决本地缓存IP地址的可能性。我没有dig
实用程序,我不知道如何检查哪个主机将结果提供给getaddrinfo()
。我仍然确定地址没有被缓存,因为我试图ping完全随机的URL。另外,由于GPRS响应时间较慢,因此在开始发送数据包之前,没有必要使用时间测量实用程序来确定ping需要1-2秒或更长时间来解析IP。此外,ncsd
,BIND
或任何dns服务器不在本地计算机上运行。我知道您可能不会将其视为证据,但这是我在系统上提供的实用工具集的原因。
我想提供一些有关互联网连接操作的其他信息。
正常连接状态
系统加载时的rc
脚本将另一个脚本作为后台进程运行:
sh /etc/connect &
connect
脚本如下:
#!/bin/sh
echo First connect attempt > /etc/ppp/conn.info
while true
do
date >> /etc/ppp/conn.info
pppd call mts
echo Reconnecting... >> /etc/ppp/conn.info
done
我在这里制作循环的原因很简单:连接会持续几个小时,之后会一直断开。不幸的是,我pppd
的实现不支持 logfile 选项(因此我无法理解为什么它会被破坏)。 persist 似乎也不起作用,所以我来到上面的连接脚本。 pppd选项是:
/dev/ttyM0 115200 crtscts
connect 'chat -f /etc/ppp/peers/mts.chat'
noauth
user mts
password mts
noipdefault
usepeerdns
defaultroute
ifconfig ppp0
给出:
ppp0 Link encap:Point-Point Protocol
inet addr:172.22.22.109 P-t-P:192.168.254.254 Mask:255.255.255.255
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:34 errors:0 dropped:0 overruns:0 frame:0
TX packets:36 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:3
RX bytes:3130 (3.0 KiB) TX bytes:2250 (2.1 KiB)
那就是它开始变得奇怪的地方。每当我连接时,我会得到不同的inet addr
,但P-t-p
始终是相同的:192.168.254.254。这与默认网关条目中显示的地址相同,由netstat -rn
:
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
192.168.254.254 0.0.0.0 255.255.255.255 UH 0 0 0 ppp0
192.168.4.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1
192.168.15.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
192.168.0.0 192.168.15.1 255.255.0.0 UG 0 0 0 eth0
0.0.0.0 192.168.254.254 0.0.0.0 UG 0 0 0 ppp0
route -Cevn
在我的系统上不可用,路由提供与上面相同的信息。
但是我永远不能ping 192.168.254.254,即使一切按预期工作:tcp连接,ping,DNS等。以下是traceroute的结果:< / p>
traceroute to kernel.org (149.20.4.69), 30 hops max, 40 byte packets
1 172.16.4.210 (172.16.4.210) 528.765 ms 545.269 ms 616.67 ms
2 172.16.4.226 (172.16.4.226) 563.034 ms 526.176 ms 537.07 ms
3 10.250.85.161 (10.250.85.161) 572.805 ms 564.073 ms 556.766 ms
4 172.31.250.9 (172.31.250.9) 556.513 ms 563.383 ms 580.724 ms
5 172.31.250.10 (172.31.250.10) 518.15 ms 526.403 ms 537.574 ms
6 pub2.kernel.org (149.20.4.69) 538.058 ms 514.222 ms 538.575 ms
7 pub2.kernel.org (149.20.4.69) 537.531 ms 538.52 ms 537.556 ms
8 pub2.kernel.org (149.20.4.69) 568.695 ms 523.099 ms 570.983 ms
9 pub2.kernel.org (149.20.4.69) 526.511 ms 534.583 ms 537.994 ms
##### traceroute loops here - why?? #######
所以,我可以假设172.16.4.210是同行的地址。在任何情况下,这样的地址都是可以ping的(见下文)。我不知道为什么traceroute输出的结构是这样的(数据包来自ISP的内部网络直到目的地,&#39;循环&#39;在目标地址 - 它不应该是这样的)。
另外我想说明我可以ping DNS服务器,但是traceroute不会一直到它。
您可能会注意到有eth0和eth1设备。他们与案件无关。 eth1未连接且eth0连接到没有Internet访问的LAN。
连接状态不佳
所以,一段时间过去了,问题就出现了。除了DNS服务器(和对等端,我从DNS的traceroute得到的地址)我无法ping通任何东西,并且无法通过tcp与远程主机通信。 DNS解析 正在运行
网络实用程序提供与正常状态相同的输出。我有相同的unpingable peer (来自ifconfig结果的192.168.254.254),路由表是相同的:
# ifconfig ppp0
ppp0 Link encap:Point-Point Protocol
inet addr:172.22.22.109 P-t-P:192.168.254.254 Mask:255.255.255.255
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:297 errors:0 dropped:0 overruns:0 frame:0
TX packets:424 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:3
RX bytes:33706 (32.9 KiB) TX bytes:27451 (26.8 KiB)
# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.254.254 * 255.255.255.255 UH 0 0 0 ppp0
192.168.4.0 * 255.255.255.0 U 0 0 0 eth1
192.168.15.0 * 255.255.255.0 U 0 0 0 eth0
192.168.0.0 192.168.15.1 255.255.0.0 UG 0 0 0 eth0
default 192.168.254.254 0.0.0.0 UG 0 0 0 ppp0
请注意,原始ppp连接(我用来提供正常状态的输出的连接)仍然存在。我的/ etc / connect脚本没有循环(脚本在临时日志中没有新记录)。
此处ping到DNS服务器:
# cat /etc/resolv.conf
#search moxa.com
nameserver 213.87.0.1
nameserver 213.87.1.1
# ping 213.87.0.1
PING 213.87.0.1 (213.87.0.1): 56 data bytes
64 bytes from 213.87.0.1: icmp_seq=0 ttl=59 time=559.8 ms
64 bytes from 213.87.0.1: icmp_seq=1 ttl=59 time=509.9 ms
64 bytes from 213.87.0.1: icmp_seq=2 ttl=59 time=559.8 ms
和traceroute:
# traceroute 213.87.0.1
traceroute to 213.87.0.1 (213.87.0.1), 30 hops max, 40 byte packets
1 172.16.4.210 (172.16.4.210) 542.449 ms 572.858 ms 595.681 ms
2 172.16.4.214 (172.16.4.214) 590.392 ms 565.887 ms 676.919 ms
3 * * *
4 217.8.237.62 (217.8.237.62) 603.1 ms 569.078 ms 553.723 ms
5 * * *
6 * * *
## and so on ###
***
行可能看起来很麻烦,但我在正常情况下为该DNS获取相同的traceroute
ping到172.16.4.210也可以正常工作。
现在转到TCP。我在PC上启动了一个简单的echo服务器,并尝试通过telnet连接到它(实际的ip地址没有显示):
# telnet XXX.XXX.XXX.XXX 9060
Trying XXX.XXX.XXX.XXX(25635)...
Connected to XXX.XXX.XXX.XXX.
Escape character is '^]'.
aaabbbccc
Connection closed by foreign host.
那就是这里发生的事情。与我的自定义应用程序中的成功connect()
一样,当telnet名为read()
时,连接已关闭... 。实际的服务器没有收到任何传入连接。为什么&#39; connect()&#39;正常返回(它无法从主机获得握手响应!)超出了我的知识范围。
同样的telnet测试在正常状态下运行正常。
注意:
我没有在我的系统的嵌入式特性的serverfault原因上发布这个。据我所知,serverfault处理更传统的系统(比如x86正在运行&#39; normal&#39; linux)。我只是希望stackoverflow有更多的嵌入式专家知道像我的Moxa这样的系统。
答案 0 :(得分:5)
问:如果其他协议似乎已关闭,我怎样才能解析DNS名称解析?
A :您的本地DNS解析程序(bind
除了ncsd
之外的另一种可能性)可能缓存第一个响应。 dig
将告诉您从哪里获得回复:
[mpenning@Bucksnort ~]$ dig cisco.com
; <<>> DiG 9.6-ESV-R4 <<>> +all cisco.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22106
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 0
;; QUESTION SECTION:
;cisco.com. IN A
;; ANSWER SECTION:
cisco.com. 86367 IN A 198.133.219.25
;; AUTHORITY SECTION:
cisco.com. 86367 IN NS ns2.cisco.com.
cisco.com. 86367 IN NS ns1.cisco.com.
;; Query time: 1 msec <----------------------- 1msec is usually cached
;; SERVER: 127.0.0.1#53(127.0.0.1) <--------------- Answered by localhost
;; WHEN: Wed Dec 7 04:41:21 2011
;; MSG SIZE rcvd: 79
[mpenning@Bucksnort ~]$
如果你从127.0.0.1
获得一个非常快速(低毫秒)的答案,那么你很可能从之前的同一DNS名称查询中得到一个本地缓存的答案(这对于人们在ppp
连接上使用缓存DNS解析器来减少连接时间,并在ppp链路上实现小的负载减少。)
如果您怀疑是缓存的答案,请对其他DNS名称执行dig
以查看是否也可以解析。
ppp
连接断开。如果您发现自己处于我描述的最后一种情况中,您需要进行一些IP和ppp级调试,然后才能进一步隔离。正如有人提到的,tcpdump
在这一点上非常有价值,但听起来你没有它。
我假设您没有与DNS服务器的同一IP地址建立TCP连接。此时有很多可能性...如果您仍然可以解析随机DNS名称,但TCP连接失败,则您可能看到的问题是在ppp连接的另一端,即内核路由缓存(它保存了一些像TCP MSS
这样的TCP状态信息,但是tcp
或者任何数量的东西都有太多的数据包丢失。
我们假设您的拓扑结构如下:
10.1.1.2/30 10.1.1.1/30
[ppp0] [pppX]
uCLinux----------------------AccessServer---->[To the reset of the network]
当您启动ppp连接时,请记下您的IP地址和默认网关的地址:
ip link show ppp0 # display the link status of your ppp0 intf (is it up?)
ip addr show ppp0 # display the IP address of your ppp0 interface
ip route show # display your routing table
route -Cevn # display the kernel's routing cache
如果您的发行版中没有iproute2
包(iproute2
提供ip
实用程序),则可以找到类似的结果:
ifconfig ppp0 # display link status and addresses on ppp0
netstat -rn # display routing table
route -Cevn # display kernel routing table
对于那些拥有iproute2
实用程序的人(这几天几乎都是每个人),ifconfig
已被弃用并被ip
命令取代;但是,如果您使用的是基于2.2或2.4的旧系统,则可能仍需要使用ifconfig
。
疑难解答步骤:
当您遇到问题时,请先检查您是否可以ping访问服务器上pppX
的地址。
pppX
的IP地址,那么除了您的uCLinux计算机上的缓存响应之外,您的DNS不太可能得到解决。pppX
,请尝试ping
TCP对等方的IP地址和DNS的IP地址(如果它不在localhost
上)。除非涉及防火墙,否则您必须能够成功ping
才能使其中任何一个工作。如果您ping
的{{1}}的IP地址但不能pppX
您的TCP对等IP地址,请检查路由表以查看您的默认路由是否仍然指向out ping
如果您的默认路由指向ppp0
,请检查您是否仍然可以ping默认路由的IP地址。
如果您可以ppp0
使用默认路由,并且可以ping
您尝试连接的远程主机,请检查内核的路由缓存中是否有远程TCP的IP地址主持人....寻找奇怪或可疑的东西
如果您可以 ping
远程TCP主机(您需要做大约200 ping
才能确定... pings
是对显着的数据包丢失和GPRS敏感是众所周知的有害的),尝试成功tcp
。如果两者都成功,那么现在是时候开始查看软件内部的线索了。
如果您仍然无法解决发生的事情,请在返回时包括上述命令的输出...以及如何开始telnet <remote_host> <remote_port>
连接。
答案 1 :(得分:-1)
Ping不应该是最终用户应用程序的一部分(参见注释),并且任何程序都不应该依赖ping来运行。最好ping可能会告诉我们远程运行TCP / IP堆栈的一部分。看我的论点here。
OP描述的问题似乎不是问题。所有网络连接都失败,解析器可能会也可能不会使用网络,ping不是真的有用。我猜想OP可以检查调制解调器是否已连接,如果它没有再连接。
编辑:伪代码
do until success
try
connect "foobar.com"
try
write data
read response
catch
not success
endtry
catch error
'modem down - reconnect
not success
end try
loop
注意:例外情况是您正在为网络人员编写网络监控应用程序。