socketConnection客户端无法释放的问题 ( 积分: 100 )

  • 主题发起人 主题发起人 风清杨
  • 开始时间 开始时间

风清杨

Unregistered / Unconfirmed
GUEST, unregistred user!
我写了一个三层,中间层放一台机,用SocketConnection来连接,<br>但scktsrvr里的客户端不会释放,同一个IP会有多个连接,<br>这样用了几天后连接数会越来越多,<br>其实我真正用的的客户端只有60个,但用了三天后它显示&nbsp;current&nbsp;Connections&nbsp;215,<br>这是什么原因,有没有什么办法解决呀?
 
TIME&nbsp;OUT&nbsp;30
 
TIME&nbsp;OUT&nbsp;30&nbsp;&nbsp;是什么意思?是不是30秒以后无用的连接会自动释放?
 
scktsrvr这个程序有问题,非正常断开的连接,即使设置了time&nbsp;out他也不能被清除掉,可以自己修改下。
 
自己修改,难道有这个程序的源码吗?在哪里可以下载?
 
Borland&nbsp;socket&nbsp;server(scktsrvr)因为突然断掉连接的原因!解决问题的办法!2007-11-10&nbsp;11:20偶来凑凑热闹。<br>前些日子,和群里面的兄弟讨论过这个问题,为此,还说了另外的一些话题,比如三次握手,滑动窗口,消息边界,心跳函数之类。如果不清楚的,请补习一下相应的知识吧,这可是底层原理,不清楚,自然不晓得为什么,客户端异常断开,服务器端侦测不到。<br>从根源上说,这是由于TCP协议的问题。TCP协议的初衷是:&nbsp;网络中断时,仍能维持通信的能力。美国国防部要求能在遭到核打击或其它灾害的时候,仍然能维持计算机之间可靠的网络通知协议。呵呵,如果客户端断开,服务器就马上释放连接。还维持什么?和初衷不符吧。要搞清楚客户端断开,为什么服务器端不能立即侦测到。这个问题,必须要理解三次握手机制。当然服务器也能侦测到异常断开,KEEPALIVE的默认时间是2小时哟。<br>详细的TCP三次握手机制:<br>客户端发送一个带SYN位的请求,向服务器表示需要连接,假设请求序号号为&nbsp;SYN&nbsp;=&nbsp;10,&nbsp;ACK=0<br>服务器接收到这样的请求后,查看是否在LISTEN的是指定的端口,不然,就发送RST=1应答,拒绝建立连接。&nbsp;如果接收连接,那么服务器发送确认,SYN为服务器的一个内码,假设为100,ACK位则是客户端的请求序号加1,本例中发送的数据是:SYN=100,ACK=11,用这样的数据发送给客户端。&nbsp;<br>客户端发送确认建立连接的消息给服务器。确认信息的SYN位是服务器发送的ACK位,ACK位是服务器发送的SYN位加1&nbsp;。<br>如果TCP连接第三次握手中,用户向服务器发送了一个SYN后就掉线了(第一步)。服务器发出SYN+ACK应答报文(第二步)。然后就再也无法收到客户端的ACK报文的。这种情况下,服务器就不断的重试,(再次发送SYN+ACK给客户端),直到超时。注意:服务器是接收到SYN请求就立即与客户端建立连接,而是先为连接请求分配内存空间,建立会话,并放到一个等待队列中。如果,这个等待的队列已经满了,那么,服务器就不在为新的连接分配任何东西,直接丢弃新的请求。这就是服务器的拒绝服务了。&nbsp;<br>因此,如果有人写一个恶意程序来试试你的Borland&nbsp;socket&nbsp;server,后果实在不敢去想。知道了问题的原因,也就能找出解决办法。解决办法就是用心跳函数。<br>在TCP中有一个Keep-alive的机制可以检测死连接,原理很简单,TCP会在空闲了一定时间后发送数据给对方:<br>1.如果主机可达,对方就会响应ACK应答,就认为是存活的。<br>2.如果可达,但应用程序退出,对方就发RST应答,发送TCP撤消连接。<br>3.如果可达,但应用程序崩溃,对方就发FIN消息。<br>4.如果对方主机不响应ack,&nbsp;rst,继续发送直到超时,就撤消连接。这个时间就是默认<br>的二个小时。<br>用keep_alive可以检测死连接,并撤消连接。但是是不是我们希望的呢?可能是,可能不是。有时可能我们希望重新通过另一个连接,来实现系统正常运转。<br>keep_alive实现:<br>type&nbsp;<br>TCP_KeepAlive&nbsp;=&nbsp;record&nbsp;<br>OnOff:&nbsp;Cardinal;&nbsp;<br>KeepAliveTime:&nbsp;Cardinal;&nbsp;<br>KeepAliveInterval:&nbsp;Cardinal&nbsp;<br>end;&nbsp;<br>var&nbsp;<br>Val:&nbsp;TCP_KeepAlive;&nbsp;<br>Ret:&nbsp;DWord;&nbsp;<br>begin&nbsp;<br>Val.OnOff:=1;&nbsp;<br>Val.KeepAliveTime:=xxx;&nbsp;<br>Val.KeepAliveInterval:=xxx;&nbsp;<br>WSAIoctl(AThread.Connection.Socket.Binding.Handle,&nbsp;IOC_IN&nbsp;or&nbsp;IOC_VENDOR&nbsp;or&nbsp;4,&nbsp;<br>@Val,&nbsp;SizeOf(Val),&nbsp;nil,&nbsp;0,&nbsp;@Ret,&nbsp;nil,&nbsp;nil)&nbsp;<br>end;<br>心跳函数:<br>客户端定时向服务器发送数据,表示自己存活着。在固定的时间内,服务器没有收到消息,就认为客户端已经断开,并释放连接。而这个过程也可以是双方的。即两边都有心跳机制。<br>Borland&nbsp;socket&nbsp;server&nbsp;具体代码实现:<br>从派生TServerClientThread线程类。<br>THeartBeatServerClientThread=&nbsp;class(TServerClientThread)&nbsp;<br>private<br>cs&nbsp;:&nbsp;TCriticalSection;&nbsp;<br><br>protected<br>…….<br>procedure&nbsp;AddClient(vHeartBeat:&nbsp;THeartBeatServerClientThread);<br>procedure&nbsp;RemoveClient(vHeartBeat:&nbsp;THeartBeatServerClientThread);<br>end;<br><br>WorkThread:&nbsp;Array&nbsp;[0..MaxLink-1]&nbsp;of&nbsp;THeartBeatServerClientThread;&nbsp;//连接队列&nbsp;<br><br>procedure&nbsp;THeartBeatServerClientThread.Execute;<br>var&nbsp;<br>theStream&nbsp;:&nbsp;TWinSocketStream;&nbsp;<br>begin&nbsp;<br>......&nbsp;<br><br>theStream&nbsp;:=&nbsp;TWinSocketStream.Create(ClientSocket,120000);&nbsp;<br><br>While&nbsp;(not&nbsp;Terminated)&nbsp;and&nbsp;(ClientSocket.Connected)&nbsp;do&nbsp;begin&nbsp;<br>try&nbsp;<br>if&nbsp;theStream.WaitForData(10)&nbsp;then&nbsp;begin&nbsp;<br>Len&nbsp;:=&nbsp;theStream.Read….<br>if&nbsp;Len=0&nbsp;then&nbsp;begin&nbsp;//客户关闭连接&nbsp;<br>ClientSocket.Close;&nbsp;<br>end&nbsp;<br>else&nbsp;begin&nbsp;<br>theStream.Write(Buffer,nLen);&nbsp;<br>end;&nbsp;<br>end;&nbsp;<br>except&nbsp;<br>ClientSocket.Close;&nbsp;//Read和Write出错,断开连接。<br>end;&nbsp;<br><br>end;&nbsp;<br><br>文章来自:&nbsp;http://www.delphibbs.com/keylife/iblog.asp?author=wu_yanan2003
 
上面是转载的.
 
问题自己解决了.就是新增一个客户端,有相同IP就释放.
 
也算是改良吧.
 
scktsrvr程序的源码Delphi自带的<br>../Borland/Delphi7/Source/Vcl<br>包括:<br>ScktCnst.pas<br>ScktComp.pas<br>ScktMain.dfm<br>ScktMain.pas<br>ScktSrvr.dpr<br>SConnect.pas<br>这几个文件
 
也遇到过相同问题,由于客户端是第三方的,不能加心跳,而且每次连接的IP也不一样,所以很麻烦。
 
后退
顶部