Pav*_*lev 3 c sockets linux networking tcp
我们正在尝试实施基于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 &
Run Code Online (Sandbox Code Playgroud)
该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
Run Code Online (Sandbox Code Playgroud)
我在这里做了一个循环的原因很简单:连接持续了几个小时,然后它总是断开.不幸的是我的实现pppd不支持logfile选项(所以我不明白它为什么会被破坏).坚持似乎也不起作用,所以我来到上面的连接脚本.pppd选项是:
/dev/ttyM0 115200 crtscts
connect 'chat -f /etc/ppp/peers/mts.chat'
noauth
user mts
password mts
noipdefault
usepeerdns
defaultroute
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
这就是它开始变得奇怪的地方.每当我连接时,我会变得不同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
Run Code Online (Sandbox Code Playgroud)
route -Cevn 在我的系统上不可用,路由提供与上面相同的信息.
但我永远无法ping 192.168.254.254,即使一切都按预期工作:tcp连接,ping,DNS等.这是traceroute的结果:
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?? #######
Run Code Online (Sandbox Code Playgroud)
所以,我可以假设172.16.4.210是对等的地址.在任何情况下,这样的地址都是可以ping的(见下文).我不知道为什么traceroute输出的结构是这样的(数据包来自ISP的内部网络到目的地,'loop'在目标地址 - 它应该不是这样的).
另外我想说明我可以ping DNS服务器,但是traceroute不会一直到它.
您可能会注意到有eth0和eth1设备.他们与案件无关.eth1未连接且eth0连接到没有Internet访问的LAN.
连接状态不良
所以,一段时间过去了,问题就出现了.除了DNS服务器(和peer,我从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
Run Code Online (Sandbox Code Playgroud)
请注意,原始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
Run Code Online (Sandbox Code Playgroud)
和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 ###
Run Code Online (Sandbox Code Playgroud)
*** 线路可能看起来很麻烦,但我在正常情况下为该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.
Run Code Online (Sandbox Code Playgroud)
那就是这里发生的事情.connect()就像在我的自定义应用程序中成功,接着是Connection关闭...当telnet被调用时read().实际的服务器没有收到任何传入连接.为什么'connect()'正常返回(它无法从主机获得握手响应!)超出了我的知识范围.
果然telnet测试在正常状态下工作正常.
注意:
我没有在serverfault上发布这个因为我的系统的嵌入性质.据我所知,serverfault处理更传统的系统(比如运行'普通'linux的x86).我只希望stackoverflow有更多的嵌入式专家知道像我的Moxa这样的系统.
问:如果其他协议似乎已关闭,我如何解析DNS名称?
答:您的本地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 ~]$
Run Code Online (Sandbox Code Playgroud)
如果您从一个非常快速(低毫秒)的答案中得到答案127.0.0.1,那么您很可能从之前的同一DNS名称查询中获得了本地缓存的答案(人们使用缓存DNS解析器的情况很常见)ppp连接以减少连接时间,以及在ppp链路上实现小的负载减少).
如果您怀疑缓存的答案,请dig对其他DNS名称执行操作以查看是否也可以解析.
ppp连接断开.如果您发现自己处于我描述的最后一种情况,您需要进行一些IP和ppp级调试,然后才能进一步隔离.正如有人提到的,tcpdump在这一点上是非常有价值的,但听起来你没有它.
我假设您没有与DNS服务器的同一IP地址建立TCP连接.此时有很多可能性......如果您仍然可以解析随机DNS名称,但TCP连接失败,则您可能看到的问题是在ppp连接的另一端,即内核路由缓存(它拥有一些像TCP状态信息一样的东西MSS搞砸了,你有太多的数据包丢失tcp或者任何数量的东西.
我们假设您的拓扑结构如下:
10.1.1.2/30 10.1.1.1/30
[ppp0] [pppX]
uCLinux----------------------AccessServer---->[To the reset of the network]
Run Code Online (Sandbox Code Playgroud)
当您启动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
Run Code Online (Sandbox Code Playgroud)
如果您没有将iproute2软件包作为发行版的一部分(iproute2提供ip实用程序),则可以找到类似的结果:
ifconfig ppp0 # display link status and addresses on ppp0
netstat -rn # display routing table
route -Cevn # display kernel routing table
Run Code Online (Sandbox Code Playgroud)
对于那些拥有iproute2实用程序的人(这几天几乎每个人都有),ifconfig已被弃用并被ip命令取代; 但是,如果你有一个较旧的2.2或2.4系统,你可能仍然需要使用ifconfig.
故障排除步骤:
当您开始遇到问题时,首先检查您是否可以ping pppX访问服务器上的地址.
pppX另一方的IP地址,那么除了uCLinux计算机上的缓存响应之外,您的DNS很可能无法解析.pppX,那么尝试pingTCP对等的IP地址和DNS的IP地址(如果它没有打开localhost).除非涉及防火墙,否则您必须能够ping成功地使用任何防火墙.如果你可以ping的IP地址,pppX但你不能ping你的TCP对等的IP地址,检查你的路由表,看看你的默认路由是否仍然指出ppp0
如果您的默认路由指向ppp0,请检查您是否仍然可以ping默认路由的IP地址.
如果您可以使用ping默认路由并且可以ping连接到您尝试连接的远程主机,请检查内核的路由缓存中是否有远程TCP主机的IP地址....查找奇怪或可疑的内容
如果您可以 ping使用远程TCP主机(并且您需要做大约200个pings以确保... tcp对重大数据包丢失敏感且GPRS是众所周知的有损),请尝试取得成功telnet <remote_host> <remote_port>.如果两者都成功,那么现在是时候开始查看软件内部的线索了.
如果您仍然无法解决正在发生的事情,请在返回时包括上述命令的输出...以及如何开始ppp连接.