【求助】C 实现HTTP客户端,向服务器请求,完成一次交互后,会主动断开连接问题

skysky 发布于 2012/04/15 15:02
阅读 3K+
收藏 2

大家好:

最近在看Andrid的HTTP发送接收文件,通过URL找到下载地址,然后完成下载内容,感觉很有意思,就用C语言写了一个简单的HTTP发送协议,但是发现了问题:
每次建立TCP连接,然后发送接收数据,再关闭TCP,然后重新建立发送接收再关闭,可以完成下载,并利用HTTP的分页,完成多包下载,但是,如果想要一次TCP连接,然后进行分包下载,等最后完成了,再断开连接,会出现问题,问题是每次完成一次交互,TCP会主动断开连接,对这个问题,我进行了下面几个论证:

1.是不是TCP程序有问题,然后写了一个简单的Socket服务器程序,随便发点数据,返回,没有问题,没有断开连接

2.用telnet连接,发送HTTP协议数据,也没问题,服务器可以正常响应,没有断开连接(未过超时时间)

3.用我的socket客户端,就会发送接收之后,就会主动断开连接.

下面为我用tcpdump截取的数据:

1.为telnet的数据图:主要特点:发送请求端,会不断发送请求,好像是心跳

22:25:51.181946 IP ubuntu.55170 > 58.83.131.110.8758: Flags [S], seq 717663714, win 5840, options [mss 1460,sackOK,TS val 646959 ecr 0,nop,wscale 5], length 0
22:25:51.205204 IP 58.83.131.110.8758 > ubuntu.55170: Flags [S.], seq 1686212697, ack 717663715, win 5792, options [mss 1452,sackOK,TS val 3066009528 ecr 646959,nop,wscale 3], length 0
22:25:51.205242 IP ubuntu.55170 > 58.83.131.110.8758: Flags [.], ack 1, win 183, options [nop,nop,TS val 646966 ecr 3066009528], length 0
22:25:54.804580 IP 58.83.131.110.8758 > ubuntu.55170: Flags [S.], seq 1686212697, ack 717663715, win 5792, options [mss 1452,sackOK,TS val 3066013128 ecr 646966,nop,wscale 3], length 0
22:25:54.804626 IP ubuntu.55170 > 58.83.131.110.8758: Flags [.], ack 1, win 183, options [nop,nop,TS val 647865 ecr 3066013128,nop,nop,sack 1 {0:1}], length 0
22:26:01.003948 IP 58.83.131.110.8758 > ubuntu.55170: Flags [S.], seq 1686212697, ack 717663715, win 5792, options [mss 1452,sackOK,TS val 3066019328 ecr 647865,nop,wscale 3], length 0
22:26:01.003976 IP ubuntu.55170 > 58.83.131.110.8758: Flags [.], ack 1, win 183, options [nop,nop,TS val 649415 ecr 3066019328,nop,nop,sack 1 {0:1}], length 0
22:26:07.225428 IP ubuntu.55170 > 58.83.131.110.8758: Flags [P.], seq 1:77, ack 1, win 183, options [nop,nop,TS val 650971 ecr 3066019328], length 76
22:26:07.249266 IP 58.83.131.110.8758 > ubuntu.55170: Flags [.], ack 77, win 724, options [nop,nop,TS val 3066025573 ecr 650971], length 0
22:26:07.249298 IP ubuntu.55170 > 58.83.131.110.8758: Flags [P.], seq 77:162, ack 1, win 183, options [nop,nop,TS val 650977 ecr 3066025573], length 85
22:26:07.274863 IP 58.83.131.110.8758 > ubuntu.55170: Flags [.], ack 162, win 724, options [nop,nop,TS val 3066025599 ecr 650977], length 0
22:26:07.853304 IP ubuntu.55170 > 58.83.131.110.8758: Flags [P.], seq 162:164, ack 1, win 183, options [nop,nop,TS val 651128 ecr 3066025599], length 2
22:26:07.880207 IP 58.83.131.110.8758 > ubuntu.55170: Flags [.], ack 164, win 724, options [nop,nop,TS val 3066026204 ecr 651128], length 0
22:26:07.881711 IP 58.83.131.110.8758 > ubuntu.55170: Flags [P.], seq 1:368, ack 164, win 724, options [nop,nop,TS val 3066026204 ecr 651128], length 367
22:26:07.881724 IP ubuntu.55170 > 58.83.131.110.8758: Flags [.], ack 368, win 216, options [nop,nop,TS val 651135 ecr 3066026204], length 0
22:26:09.849251 IP ubuntu.55170 > 58.83.131.110.8758: Flags [P.], seq 164:240, ack 368, win 216, options [nop,nop,TS val 651627 ecr 3066026204], length 76
22:26:09.921683 IP 58.83.131.110.8758 > ubuntu.55170: Flags [.], ack 240, win 724, options [nop,nop,TS val 3066028245 ecr 651627], length 0
22:26:09.921718 IP ubuntu.55170 > 58.83.131.110.8758: Flags [P.], seq 240:325, ack 368, win 216, options [nop,nop,TS val 651645 ecr 3066028245], length 85
22:26:09.944758 IP 58.83.131.110.8758 > ubuntu.55170: Flags [.], ack 325, win 724, options [nop,nop,TS val 3066028268 ecr 651645], length 0
22:26:10.177510 IP ubuntu.55170 > 58.83.131.110.8758: Flags [P.], seq 325:327, ack 368, win 216, options [nop,nop,TS val 651709 ecr 3066028268], length 2
22:26:10.203175 IP 58.83.131.110.8758 > ubuntu.55170: Flags [.], ack 327, win 724, options [nop,nop,TS val 3066028527 ecr 651709], length 0
22:26:10.204722 IP 58.83.131.110.8758 > ubuntu.55170: Flags [P.], seq 368:734, ack 327, win 724, options [nop,nop,TS val 3066028527 ecr 651709], length 366
22:26:10.204737 IP ubuntu.55170 > 58.83.131.110.8758: Flags [.], ack 734, win 250, options [nop,nop,TS val 651715 ecr 3066028527], length 0
22:26:11.789812 IP ubuntu.55170 > 58.83.131.110.8758: Flags [P.], seq 327:403, ack 734, win 250, options [nop,nop,TS val 652112 ecr 3066028527], length 76
22:26:11.855183 IP 58.83.131.110.8758 > ubuntu.55170: Flags [.], ack 403, win 724, options [nop,nop,TS val 3066030179 ecr 652112], length 0
22:26:11.855212 IP ubuntu.55170 > 58.83.131.110.8758: Flags [P.], seq 403:488, ack 734, win 250, options [nop,nop,TS val 652128 ecr 3066030179], length 85
22:26:11.879596 IP 58.83.131.110.8758 > ubuntu.55170: Flags [.], ack 488, win 724, options [nop,nop,TS val 3066030203 ecr 652128], length 0
22:26:12.101337 IP ubuntu.55170 > 58.83.131.110.8758: Flags [P.], seq 488:490, ack 734, win 250, options [nop,nop,TS val 652190 ecr 3066030203], length 2
22:26:12.123215 IP 58.83.131.110.8758 > ubuntu.55170: Flags [.], ack 490, win 724, options [nop,nop,TS val 3066030447 ecr 652190], length 0
22:26:12.124718 IP 58.83.131.110.8758 > ubuntu.55170: Flags [P.], seq 734:1100, ack 490, win 724, options [nop,nop,TS val 3066030447 ecr 652190], length 366
22:26:12.124734 IP ubuntu.55170 > 58.83.131.110.8758: Flags [.], ack 1100, win 283, options [nop,nop,TS val 652195 ecr 3066030447], length 0
22:26:13.977258 IP ubuntu.55170 > 58.83.131.110.8758: Flags [P.], seq 490:566, ack 1100, win 283, options [nop,nop,TS val 652659 ecr 3066030447], length 76
22:26:14.045135 IP 58.83.131.110.8758 > ubuntu.55170: Flags [.], ack 566, win 724, options [nop,nop,TS val 3066032369 ecr 652659], length 0
22:26:14.045303 IP ubuntu.55170 > 58.83.131.110.8758: Flags [P.], seq 566:651, ack 1100, win 283, options [nop,nop,TS val 652676 ecr 3066032369], length 85
22:26:14.074251 IP 58.83.131.110.8758 > ubuntu.55170: Flags [.], ack 651, win 724, options [nop,nop,TS val 3066032398 ecr 652676], length 0
22:26:14.345366 IP ubuntu.55170 > 58.83.131.110.8758: Flags [P.], seq 651:653, ack 1100, win 283, options [nop,nop,TS val 652751 ecr 3066032398], length 2
22:26:14.368128 IP 58.83.131.110.8758 > ubuntu.55170: Flags [.], ack 653, win 724, options [nop,nop,TS val 3066032692 ecr 652751], length 0
22:26:14.369649 IP 58.83.131.110.8758 > ubuntu.55170: Flags [P.], seq 1100:1466, ack 653, win 724, options [nop,nop,TS val 3066032692 ecr 652751], length 366
22:26:14.369693 IP ubuntu.55170 > 58.83.131.110.8758: Flags [.], ack 1466, win 317, options [nop,nop,TS val 652757 ecr 3066032692], length 0
22:26:16.241569 IP ubuntu.55170 > 58.83.131.110.8758: Flags [P.], seq 653:729, ack 1466, win 317, options [nop,nop,TS val 653225 ecr 3066032692], length 76
22:26:16.304111 IP 58.83.131.110.8758 > ubuntu.55170: Flags [.], ack 729, win 724, options [nop,nop,TS val 3066034628 ecr 653225], length 0
22:26:16.304134 IP ubuntu.55170 > 58.83.131.110.8758: Flags [P.], seq 729:814, ack 1466, win 317, options [nop,nop,TS val 653240 ecr 3066034628], length 85
22:26:16.329515 IP 58.83.131.110.8758 > ubuntu.55170: Flags [.], ack 814, win 724, options [nop,nop,TS val 3066034653 ecr 653240], length 0
22:26:16.581089 IP ubuntu.55170 > 58.83.131.110.8758: Flags [P.], seq 814:816, ack 1466, win 317, options [nop,nop,TS val 653310 ecr 3066034653], length 2
22:26:16.607685 IP 58.83.131.110.8758 > ubuntu.55170: Flags [.], ack 816, win 724, options [nop,nop,TS val 3066034932 ecr 653310], length 0
22:26:16.609115 IP 58.83.131.110.8758 > ubuntu.55170: Flags [P.], seq 1466:1832, ack 816, win 724, options [nop,nop,TS val 3066034932 ecr 653310], length 366
22:26:16.609125 IP ubuntu.55170 > 58.83.131.110.8758: Flags [.], ack 1832, win 350, options [nop,nop,TS val 653317 ecr 3066034932], length 0
22:26:21.608549 IP 58.83.131.110.8758 > ubuntu.55170: Flags [F.], seq 1832, ack 816, win 724, options [nop,nop,TS val 3066039933 ecr 653317], length 0
22:26:21.608698 IP ubuntu.55170 > 58.83.131.110.8758: Flags [F.], seq 816, ack 1833, win 350, options [nop,nop,TS val 654566 ecr 3066039933], length 0
22:26:21.633500 IP 58.83.131.110.8758 > ubuntu.55170: Flags [.], ack 817, win 724, options [nop,nop,TS val 3066039958 ecr 654566], length 0

2.为我的socket程序,有长度为0发送,超时之后,接着就是返回FIN,而telnet最少为2字节发送包

C22:40:12.333177 ARP, Request who-has localhost tell ubuntu, length 28
22:40:12.333447 IP ubuntu.55174 > 58.83.131.110.8758: Flags [S], seq 2902135279, win 5840, options [mss 1460,sackOK,TS val 862247 ecr 0,nop,wscale 5], length 0
22:40:12.360017 IP 58.83.131.110.8758 > ubuntu.55174: Flags [S.], seq 2602269771, ack 2902135280, win 5792, options [mss 1452,sackOK,TS val 3066870700 ecr 862247,nop,wscale 3], length 0
22:40:12.360040 IP ubuntu.55174 > 58.83.131.110.8758: Flags [.], ack 1, win 183, options [nop,nop,TS val 862254 ecr 3066870700], length 0
22:40:12.360280 IP ubuntu.55174 > 58.83.131.110.8758: Flags [P.], seq 1:164, ack 1, win 183, options [nop,nop,TS val 862254 ecr 3066870700], length 163
22:40:12.387379 IP 58.83.131.110.8758 > ubuntu.55174: Flags [.], ack 164, win 724, options [nop,nop,TS val 3066870728 ecr 862254], length 0
22:40:12.388912 IP 58.83.131.110.8758 > ubuntu.55174: Flags [P.], seq 1:368, ack 164, win 724, options [nop,nop,TS val 3066870729 ecr 862254], length 367
22:40:12.389445 IP ubuntu.55174 > 58.83.131.110.8758: Flags [.], ack 368, win 216, options [nop,nop,TS val 862262 ecr 3066870729], length 0
22:40:17.389198 IP 58.83.131.110.8758 > ubuntu.55174: Flags [F.], seq 368, ack 164, win 724, options [nop,nop,TS val 3066875730 ecr 862262], length 0
22:40:17.389377 IP ubuntu.55174 > 58.83.131.110.8758: Flags [P.], seq 164:346, ack 369, win 216, options [nop,nop,TS val 863512 ecr 3066875730], length 182
22:40:17.389809 IP ubuntu.55174 > 58.83.131.110.8758: Flags [F.], seq 346, ack 369, win 216, options [nop,nop,TS val 863512 ecr 3066875730], length 0
22:40:17.418309 IP 58.83.131.110.8758 > ubuntu.55174: Flags [.], ack 347, win 858, options [nop,nop,TS val 3066875759 ecr 863512], length 0
22:40:39.899924 IP 58.83.131.110.8758 > ubuntu.55172: Flags [S.], seq 2529907785, ack 241179076, win 5792, options [mss 1452,sackOK,TS val 3066898241 ecr 845534,nop,wscale 3], length 0
22:40:39.899943 IP ubuntu.55172 > 58.83.131.110.8758: Flags [R], seq 241179076, win 0, length 0

 

通过以上问题,我想知道是否是因为telnet里实现了心跳机制,所以可以一次连接,多次会话,而我的socket程序没有?如果这样的话,那我简单的第一个测试,也没有出现断开连接的问题,所以我困惑了,希望大家帮忙看看,这是什么因素了?


以下是问题补充:

@skysky:又看了看数据,看了看TCP/IP协议,两种情况都符合协议,就是没明白,为什么用socket完成数据后发送一个确认请求之后,5s内我已经发送了第二条请求,但是TCP/IP在发送请求前会先等待超时回复一个FIN,再将我的请求发出去,而telnet不会回复这个FIN,5s后会发出FIN,我怀疑是不是我的接收函数有问题! (2012/04/16 10:24)
加载中
0
skysky
skysky
问题找到了,将TCP/IP卷,又细细琢磨了一下,问题不出在TCP/IP,而是
1.Keep-Alive: timeout=5, max=100这个参数的因素,max减为了1
2.我的接收函数,是阻塞的,所以会死等,超过了5s,这两个因素导致了socket失败,谢谢大家了!稍后,我把整理的源码拿出来分享一下!
0
捞炳成
skysky
skysky
什么是的?
0
中山野鬼
中山野鬼
楼主用的什么socket库?WIN还是LINUX下的。
skysky
skysky
Linux的
0
tsuibin
tsuibin

在HTTP协议中

在你成功链接服务器之后,服务器会返回状态码,状态状态码说明了请求状态,

成功请求之后返回200,然后开始接收页面数据,数据发送完,断开链接

skysky
skysky
是这样的,我现在不想让它断开连接,想要继续发送其他指令,因为建立一次TCP连接需要消耗时间,想要一次连接,多次会话
0
教父独白
教父独白
不可能吧,HTTP的协议,完成一次请求后,服务器会主动断开连接。你可以参考下comet的长连接
skysky
skysky
可以保持长链接,就是通过max属性控制,也可以完成一次交互就断掉,HTTP1.1支持长链接
0
陈舵主
陈舵主
这个我现在也在搞,想实现长连接,楼主把你的代码分享下啊
0
陈舵主
陈舵主
还有请教楼主,公司上网用的代理,我怎么通过http请求访问页面代码
0
skysky
skysky
没问题,改天共享出来!
返回顶部
顶部