很久很久以前

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  34 随笔 :: 4 文章 :: 17 评论 :: 0 Trackbacks

2007年5月17日 #

Winsock 10053错误分析

 WSAGetLastError可能会返回10053错误,查msdn的解释是:

WSAECONNABORTED 10053

Software caused connection abort.

An established connection was aborted by the software in your host computer, possibly due to a data transmission time-out or protocol error.

神马?软件原因造成的连接中断,这是什么意思,不跟没说一样的么?
google一下呗

Berkeley description:

A connection abort was caused internal to your host machine. The software caused

a connection abort because there is no space on the socket’s queue and the socket

 cannot receive further connections.

       

WinSock description:

Partly the same as Berkeley. The error can occur when the local network system aborts

a connection. This would occur if WinSock aborts an established connection after data

retransmission fails  (receiver never acknowledges data sent on a datastream socket).

       

TCP/IP scenario:

A connection will timeout if the local system doesn’t receive an (ACK)nowledgement for

data sent.  It would also timeout if a (FIN)ish TCP packet is not ACK’d

(and even if the FIN is ACK’d, it will eventually timeout if a FIN is not returned).

 

伯克利说这种连接中断是因为宿主机器的内部原因,因为软件导致的连接中断,可能是因为socket的队列满并且这个socket不能接收更多的连接了。
这还不如不说,越说越糊涂了。
winsocket的描述,似乎还靠谱一些,这种错误一般发生在一个建立的连接被重发失败的情况下产生,接收方没有响应数据发回来。但还是比较模糊。
再看看tcp ip标准文档的说法,如果本地系统没有收到发送数据的响应(ack)那么这连接就会超时。如果tcp的fin包没有被ack(或者fin包被ack了但fin没有返回)那么也会超时。但是,但是,超时跟这个10053有神马关系?
再看后续的解释:
从参考1中找到如下的描述:

The Scenario: 
An HTTP POST is to be sent to an HTTP server.
The server begins reading the POST and notices that the HTTP request header is invalid.
It immediately sends an HTTP response (with an error status, perhaps status=400) and closes the connection without trying to continue reading the remainder of the HTTP request that is forthcoming.

Meanwhile, the client is still happily writing the remainder of the HTTP request to the socket. (Remember a TCP/IP socket connection needs to be closed from both sides. In this case, the server has closed its side, but the client is still pumping data into the half-open connection.)
The client finishes writing the HTTP POST to the socket — meaning that data has been buffered to Winsock. The client application then tries to read the HTTP response, but it cannot because the outgoing retransmission (of the buffered data by WinSock) failed and the socket connection was shutdown on the client side (by Winsock). Even though the HTTP server sent the response, it is lost and cannot be retrieved. The error your application will receive when
trying to read the HTTP response on the socket is WSAECONNABORTED. The word "software" in any of the above error messages refers to "WinSock".

Go back and re-read the original error explanations. Hopefully, after that explanation, you’ll say "Aha! I understand what they’re talking about!".

 

啊哈,又有http了,大概意思就是http server收到请求了,但发现有问题,那么回一个http错误码,然后就关闭了socket,但与此同时,client端还在很开心地向socket写数据,注意哦,tcp是全双工的。client写完毕后,实际上数据只是放到了发送方的缓冲区中,不一定已经发出去了,如果写得不好的程序,这个时候就开始从socket读数据了,这时候就会产生一个WSACONNECTABORTED错误,windows上对应的就是10053错误。

但这个解释实际上是不能让人满意的,只是举出了一种场景,但为什么会产生还没有解释。后面又搜到了个参考2,首先解释10053错误是收到fin后client会放弃发送缓冲区中的数据,同时上报错误。虽然说法还有点一头雾水。

不过这两个参考给我们一个思路,重现这个问题。

于是简单写个测试用的c-s程序,大概流程如下

 

 

图1 CS程序简化流程图

这个简单程序演示如何出现10053错误(以及10054错误)。

如果server在收到client发送的数据后立即关闭socket,那么client再读时,会收到10053错误;如果server收到发送数据后,立即crash,那么随后client再读取时会收到10054错误。

ok,能够重现场景了,那么我们来分析一下更细节的方面,网络问题自然是抓包,本问题处理抓包还要看一下tcp的状态以便辅助分析,我们在client端每次操作之前都打印当前的tcp状态。

下面是client端发送记录和对应的netstat情况

图2 10053错误client端tcp状态流转

client在发送之前tcp状态是established,在发送之后,server会立即关闭,tcp状态也变为close_wait,但这只是单方向的关闭,client可以继续发数据,但client发送后,server立即退出了,导致后续recv会失败并且返回10053。对应抓包情况如下:



图3 10053错误client端tcp抓包

整个通信过程如下:
1-3.三次握手建立连接
4.客户端(10.10.86.93)向服务器端(10.10.86.98)发送数据,1字节
5.server 中止 发送fin(同时ack之前那个push)
6.client ack 那个fin
7.client再发送两个字节
8.server此时已经关闭socket,属于非正常情况,回复复位命令

整个过程可以重现10053情况,tcp发送分组数据的情况也一目了然,事情到此就可以了么?显然不是,你也看到了后面还有很多文字,不知此时你心中的问题是否跟我一样,先说我自己的吧,通过抓包发现这里的异常关闭有个reset,但reset一般是10054(Connection reset by peer)的错误,那么10053与10054的区别在哪里。要搞清楚问题也不难,重现场景抓包分析。
以下是修改上面的cs程序,在client发送的1字节包后,立即crash,这导致的问题是操作系统会立即回收所有资源,包括socket资源。




图4 10054错误client端tcp状态流转

可以看到在crash之前这个tcp都是established状态。crash之后,client端接收数据时会收到10054错误,场景重现了,我们再看一下抓包情况



图5 10054错误client端tcp抓包

这个抓包情况跟10053很像,1-7也同10053,在8时,client收到server发过来的reset,表示当前连接被强制复位了。
对比10053和10054可以发现,如果srv返回fin标志后再reset那么对应的错误就是10053,如果直接reset就是10054错误。回过头来在看参考2中的说法也就有点感觉了。

总结一下:
1.遇到不了解的问题,google是非常好的方法
2.对于一般问题,重现之很重要,可以反复发现问题并验证问题。自己写程序或者搭环境尽量重现。
3.网络问题抓包是利器,包括各种工具的使用netstat wireshark ping traceroute等。
4.多重问题对比其中的差异,这里对比10053错误和10054错误。
5.理论基础要搭好,本次问题主要是tcp的异常断开问题,熟悉tcp断开的半关闭和复位逻辑,不过理论还是理论,同样是复位在不同场景下的错误码不同。并且实现上也跟具体的操作系统相关。
6.实际工作中,
10053错误时,用户主要是处于透明代理情况,那么这一般是又有用户所在的代理服务器异常关闭导致的,可能跟我们的离线文件私有协议被用户所在的代理服务器拒绝掉导致的。

7.回过头来在看一开始的解释,所谓软件原因造成的连接终端,就是本例子中,server端在shoutdown本方向传输时,立即关闭了socket,导致本应该等待对方发送fin来完全结束的正常逻辑被打破,编程单方向强制中止本次tcp,导致client端之后向上报错,就是所谓的10053错误了,这里的软件就是server端的那个程序。(不过也有种说法是,客户端发送错误数据,导致server端保护机制而强制关闭)


参考:

  1. http://www.chilkatsoft.com/p/p_299.asp   
  2. http://bbs.csdn.net/topics/360024280#post-361829232
  3. 《TCP/IP详解(卷一)》18章 TCP连接的建立和中止

 

 

posted @ 2013-11-28 11:22 Long Long Ago 阅读(29094) | 评论 (1)编辑 收藏

最近改造文件传输,参考libcurl,考虑到他支持那么多协议,但我只关心http的,所以考虑是否可以只生成http支持的版本,查了一下,果然可以。
下载,如果不需要最新的,那么只要下载个zip包就好了。
通过download wizard可以指引你下载不同的版本:http://curl.haxx.se/dlwiz/
选择
source code - 平台无关- 找到最新版本下载,解压缩
编译比较简单有build指令
不过我从vs目录下找到一个2005版本的vcproj文件,用这个也可以编译,不过要设置一下include目录为../../../include
 上面是废话了,关键的怎么值生成对http的支持呢
只要在编译指令中增加定义HTTP_ONLY宏就可以了,就这么简单。
详细说明在这里http://curl.haxx.se/docs/install.html
posted @ 2013-11-21 20:40 Long Long Ago 阅读(682) | 评论 (0)编辑 收藏

路由器软件部分的几个概念:CFE、固件(Firmware)、NVRAM
CFE的作用跟PC的BIOS一样是负责引导操作系统的;固件就是路由器的操作系统,就像PC上的Windows一样;NVRAM则用于存储路由器的设置,相当于PC的CMOS。
当路由器插上电后自动进入CFE,CFE进行类似PC的BIOS那样进行自检,自检通过后就引导路由器的固件了(相当于的PC的Windows了),正常情况下最多一分钟路由器的固件就会引导完毕,并且Power灯是常亮的。如果Power灯一闪一闪,那一般是CFE没有引导成功路由器的固件(固件不存在、不正确、已损坏等等)。
那么我们平常刷固件会把CFE也刷了吗?呵呵,不会的,就像你平时装Windows一样,不管你是装XP也好,Vista也好,Win7也好,都不会对你的BIOS进行更新。那我想刷CFE该用什么方法?一般用户用路由器原厂的CFE即可,如果要玩的深入一些想刷CFE,那么可以通过JTAG或者telnet方式来刷(比较危险,而且受固件限制,有些固件不支持)。
主要是对硬件环境进行初始化,image的更新,加载kernel等
posted @ 2013-11-13 20:34 Long Long Ago 阅读(238) | 评论 (0)编辑 收藏

好久没有更新这个blog了,java也放下了许久。现在开始重新更新本blog
posted @ 2010-10-30 13:44 Long Long Ago 阅读(224) | 评论 (0)编辑 收藏

本文主要介绍了JXTA中的各种概念。
1.Peer。一个peer就是实现了一个或多个JXTA协议的网络设备。比如传感器,电话, PDA,PC,服务器,巨型机等等。每一个peer与其他peer都是独立操作并且是异步的。有peer ID来唯一标识一个peer。peer使用JXTA协议公开一个或多个网络接口(network interface),每一个公开的接口都被广告为一个peer端点(peer endpoint),这个peer端点唯一标识了一个网络接口。peer之间不需要有直接的点对点的网络连接。可以使用中间的peer作为peer的消息路由,将由于硬件网络或者网络配置(NATs,防火墙或者代理)而造成的两个通信peer进行互联。peer通常被设计成网络中自然地互相发现,从而构成暂时的或持久的关系成为peer组(peer gorup)。
2.Peer Group.一个peer组是一个peer的集合,这些peer都有一组相同的服务。peer自组织的加入到peer组中,并通过一个唯一的peer组id来区别这些peer组。每一个peer组都可以建立一个属于自己的memebership policy,从任何人可以加入到最严格的安全验证以及受保护方式(需要完全的认证书来加入)。一个peer可以同时属于多于一个peer组。默认地,第一个peer组被实例的组是Net Peer Group。所有的peer都属于Net Peer Group。peer可以选择加入其他的peer group。JXTA协议描述了peer如何公开,发现,加入以及监控peer组。
     如下几点说明了创建peer组的目的。
  1. 建立安全的环境。peer组可以创建一个本地控制域,在这个域中使用一个特定的安全策略。这个安全策略可以简单的只是一个明文的帐号 /口令交换,也可以像PKI一样成熟。peer组界定认证的成员访问和公开受保护的内容(content)。peer组在建立了一个逻辑上的区域,从而对访问peer组的资源进行界定。
  2. 创建一个范围环境。peer组裕兴建立一个本地的专用域。比如,peer可以组织起来实现一个文档共享网络或者一个CPU共享网络。 peer组提供细分网络成抽象的区域来提供内在范围机制(implicit scoping mechanism)。比如,当搜索一个组内容的时,peer组可以界定定义一个搜索范围。
  3. 创建一个监视环境。peer组允许一个peer为了任何目的去监视一组peer(比如,心跳,traffic introspection或者accountability)。peer组也可以构建一个父子层次结构,其中任何一个组都有一个唯一的父亲。查询请求能偶在这个组中传播。对于这个组中的广告也可以在其父组中公开,当然也包裹这个组本身。
peer组提供了一组服务成为peer组服务。在JXTA中敌营了一个核心peer组服务集合。两个peer如果要通过一个服务进行交互,他们配需位于同一个peer中。
    核心的组服务有如下:
  1. 发现服务(Discovery Service)。本服务被组中的peer用来查询per组资源,比如peer,peer组,通道和服务等。
  2. 成员关系服务(Membership Service)。本服务被当前成员用来拒绝或接受一个新的组成员应用。一个peer想要加入到一个group前,首先要确定一个当前的成员,并请求加入。当前成员的集合可以拒绝或者接受某个想加入的应用(application)。本服务可能会发起一个所有peer或者指定组代表的一次投票来决定是否接受或者聚居新的成员应用。
  3. 访问服务(Access Service)。使用访问服务可以用来验证一个peer对另一个peer的请求(request)。如果访问被允许,那么接受请求的peer会提供给请求peer关于该请求所要知道的信息的信任和相关信息。(注意,在peer组中,不是所有的行为(action)都需要通过访问服务的检查,只有那些在某些peer中被限制的行为在需要调用时,才被检查。)
  4. 管道服务(Pipe Service)。本服务用于在peer组成员间的链接管道的建立和管理。
  5. Resolver服务。本服务用来发送一般的查询请求到其他的peer。peer可以定义和交换请求以便发现任何需要的信息(比如一个服务的状态或者一个管道端点的信息。)
  6. 监视服务(Monitoring Service)。本服务用来让一个peer监视本组中的其他成员服务。
    不是所有上面提到的服务都必须要被每个peer实现。一个peer组可以自由的实现那些它认为有用的服务,并可以依赖于默认的Net Peer Group来提供非关键核心服务的一般实现。
3.Network Services。peer之间可以协作并通信以发布,发现和启动网络服务。peer可以发布多个服务。peer通过Peer Discovery Protocol来发现network service。在JXTA协议中组织了两个层次上的network service。
  • Peer Service。一个peer service只有当peer公布了自己的service时才能被访问。如果这个peer失败了,那么它的service也失败了。不同的peer可以运行某个服务的多个实例,但每个实例都必须公开自己的广告(advertisement).
  • Peer Group Service。peer组服务是这个组中成员所运行服务的实例的集合的组织形式,其中这些实例是互相合作的。如果其中任何一个peer失败了,那么这个 peer组服务将不会收到影响(假定这个服务可以从其他peer获得)。peer group服务通过peer 组广告的以部分来发布。
    服务可以是事先被安装到peer上或者通过网络安装的。为了真正的运行一个服务,peer必须为定位一个适合当前peer运行环境的一个实现。这个从网络上查找,下载和安装一个服务的过程很类似于在Internet上搜索一个Web页面,取回这个页面然后再安装需要的插件的过程。
4.Modules。JXTA的module用来描述任何一段用来实现JXTA world中一个行为的“代码”的抽象表示(Abstraction)。Network Service就是在一个peer上实现的行为的一个最一般的例子。这个Module Abstraction不一定特指什么“代码”,它可以是一个Java类,也可以是Java jar,或者动态链接库dll,一个XML消息或是一个脚本。这个module的行为交给了module的实现者。对于一个实例(instance), module表示了一个网络服务(network service)在不同平台上的不同实现,这些平台比如说在java平台,MS windows平台,Solaris 平台。
    Module允许peer实现一个新的行为,通过提供了一个一般的抽象。当peer浏览或者加入一个peer组时,他可以查找新的其打算实现的行为。比如,当加入一个peer组后,一个peer可能必须学习新的搜索服务,这个服务只能在本peer组中使用。为了加入到这个组,这个peer必须实现这个新的搜索服务。这个module框架可以启动平台无关行为的表示(representation)和广告(advertisement)。并允许peer描述和实现任何形式这个行为(behavior)的是实现。比如,一个peer使用java或者c实现一个行为的实现。
& amp; nbsp;   描述和公告一个平台独立的行为的能力能有有效的支持peer组包含异构的peer。module的广告可以使JXTA的peer能够采用平台独立的方式描述一个行为。JXTA平台使用module广告来自描述。
    module抽象(Module abstractIon)包括一个module class,module specification和一个moduleimplementation。
  • Module Class。module class主要用于广告一个行为(behavior)的存在。这个class的定义表述了一个期望的行为和一个期望的对所支持的module的绑定。每一个module class都有一个唯一的ID,成为MoudleClassID
  • Module Specification。Module Specification主要用于访问这个module。它包含了访问或者启动这个module的所有必要的信息。比如,一个服务,他的module specification可能包含了一个用于和其他服务相通信的管道的广告。一个module specification用于提供module class所指明的功能。对于一个module class可能有多个module specification。每一个module specification都有一个唯一的id,ModuleSpecID。ModuleSpecID包含了ModuleClass ID,并指明了所使用的module class。一个module specification暗含了对网络的兼容性。对于一个给定的module specification的所有实现都必须使用相同的协议,这些实现都需要是兼容的,即使使用不同的语言实现的。
  • Module Implementation。Module Implement是一给定module specification的实现。对于一个module specification可以有多个module implementation。每一个module implementation都包含了它所实现的与specification相关联的ModuleSpecID。
    Module可以被peer组服务使用,也可以被独立的服务所使用。JXTA服务通过module abstraction来区别存在的服务(他的Module Class),服务的specification(Module Specification),或者服务的实现(Service Implementation)。所有的这些都有一个联合的广告,并且可以通过其他JXTA peer来公告和发现的。作为一个例子,考虑JXTA的发现服务。它包含一个唯一的ModuleClassID,标识了他作为一个发现服务——他的抽象功能。对于这个发现服务可以有多个不同的规范(Specification),并伴随着不同的实现。对于组的大小和在网络中的传播方式可以使用不同的裁剪策略。每一个Specification都有唯一的MdouleSpecID,其中指明了发现发现服务的ModuleClassID。对于每个规范,都可能有多种实现,每种实现都包含了相同的ModuleSpceID。
    总之,对于一个给定的module Class都可能有多种规范,这些规范可能是完全不同的。然而任何给定规范的所有实现都是假定可以互相兼容的。
posted @ 2007-05-19 23:11 Long Long Ago 阅读(936) | 评论 (0)编辑 收藏

JFace的单独使用很久都没有做过,基本上都是在开发elcipse插件时用JFace。今天使用JFace作为Java Application时遇到了 Exception in thread "main" java.lang.NoClassDefFoundError: org/eclipse/core/runtime/IStatus 错误,虽然已经添加了org.eclipse.jface,org.eclipse.core.runtime,org.eclipse.osgi包,但仍然出错,后来发现org.eclipse.core.runtime.IStatus是在org.eclipse.equonix.common包中,添加后发现 ,还需要添加org.eclipse.core.command包,再添加后搞定。
posted @ 2007-05-17 14:33 Long Long Ago 阅读(1039) | 评论 (2)编辑 收藏

    以前实现SWT中的模式和非模式窗体(modal or non-modal window )是通过在子窗体中是否截取父窗体的消息循环来实现的,现在发现这样好像不行了,但可以通过指定子窗体的样式(style)来制定子窗体是否是模式窗体。
Shell child = new Shell(shell,SWT.SHELL_TRIM|SWT.APPLICATION_MODAL);
上面的语句指定了子窗体child为模式窗体。在上面的style中指定SWT.SHELL_TRIM 是为了显示窗体的三个默认按钮(最大,最小和关闭),也可以用SWT.DIALOG_TRIM,不过此时为对话框样式,只有一个默认按钮(关闭)。默认的Shell是非模式窗体,并且是有默认系统按钮的,即样式为:SWT.SHELL_TRIM|SWT.MODELESS。
顺便说一下,在JFace的Dialog中使用模式对话框只要简单的设置该对话框setBlockOnOpen(true)即可。
posted @ 2007-05-17 14:27 Long Long Ago 阅读(2103) | 评论 (0)编辑 收藏