首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VB >

讨论:浅谈winsock ConnectionRequest事件,该如何处理

2011-12-30 
讨论:浅谈winsock ConnectionRequest事件近期一直在研究sock编程(各种穿透代理服务器的方法),从控件级的编

讨论:浅谈winsock ConnectionRequest事件
近期一直在研究sock编程(各种穿透代理服务器的方法),从控件级的编写到纯API的编写,在写了几个案例后,发现在使用控件编程时,二个事件的区别与费解。

在使用winsock编程时,会用到以下二个事件:Connect和ConnectionRequest
可能有朋友会说了,我在编写sock程式时并没有用到connect事件,只用了ConnectionRequest事件,达到了一样的效果(数据能够正确互通)。

Connect: 当一个 Connect 操作完成时发生。
ConnectionRequest: 当远程计算机请求连接时出现。

OK,上面是MSDN对上面二个事件的描述,仅从上面的描述来讲,只要是AB二地的通道正常打开,那么上面二个事件都将发生。

我们来举个例子(TCP为例):
A地(发起请求):

WinSock1.RemoteHost = “**.***.***.***”
WinSock1.RemotePort = 9000
WinSock1.connect

B地(响应请求):

Winsock1.LocalPort = 9000
Winsock1.Listen

调试上面的代码,你会发现仅当A地发出connect方法时,B地的ConnectionRequest事件才会进行响应

B地:
Private Sub Winsock1_ConnectionRequest(ByVal requestID As Long)
‘仅当A地发出connect请求时,这里才会进行响应
dim strSend as string:strSend=”SendData”
Winsock1.Accept requestID

Do Until Winsock1.State = 7
  DoEvents
Loop

  Winsock1.SendData strSend
End Sub

A地:
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
‘这里接收数据
End Sub
我看过许多VB程序员用上面的代码,写winsock程式,并且这么写也可以达到他们想要的效果(数据传输)。

那么如果我说上面的发送数据方代码有问题,你肯定会用鸡蛋砸我。
不知道这么写代码的程序员,有没有想过一个问题:就是我一开始就提出的

“OK,上面是MSDN对上面二个事件的描述,仅从上面的描述来讲,只要是AB二地的通道正常打开,那么上面二个事件都将发生。”

现在AB二地的通道已经打开,那么connect事件,究竟做了点啥?是不是微软疯了,同样的功能事件,设计员设计了相同的二个???

我刚才说了上面的发送方代码有问题:发送方端容易出现死循环
上面代码中,用循环不停的测试state的状态,仅当state=7时,才会终止循环,否则一直在移交控制权。
在大规模使用winsock的情况下,服务器端sock控件往往以数组形式出现,也就是说同一个sock控件会响应来自不同客户端的请求,而每个请求,服务器在接收后,都会进行一系列的处理(此时客户端state永远不会为7),然后才会响应客户端。也就是说如果服务器端在处理某个通道的逻辑时,发现了意外,那么此时此通道的客户端代码将变成死循环,可能你会说那是你服务器端代码写的不好,跟客户端代码没关系,但对于每个有点职业道德的程序员来讲,是不能够让自己的代码出现死循环的(这里指的是所有的商业代码)

那么如果是我,我会怎么改上面的代码呢,很简单我会用connect事件,接收服务端响应

Private Sub Winsock1_Connect()
Debug.print Winsock1.State
  Winsock1.SendData strSend
End Sub

在Connect事件,如果你愿意可以像我一样每次响应时,都抛出state状态,看看它的状态是什么?

上面所写,仅代表个人意见与看法,欢迎大家讨论,有不对的地方请指正,谢谢!


[解决办法]
TCP/IP协议详解 第二册第一个例子的代码,你可以简单看下
connect 请求连接
listen 监听连接
ConnectionRequest 接收连接,返回确认,类似如下:

客户端服务器
||
请求连接监听请求
||
等待接收请求
||
等待返回标识(假设返回确认)
||
建立连接建立连接

客户端根据服务端的返回标识建立连接 

其实这和TCP的三次握手很类似

如果有不对的地方请老大们指出,谢谢
[解决办法]
汗 我的tab都被CSDN吃了
[解决办法]
深奥呀
[解决办法]
每个事件都有它自己的作用,对于一次连接过程来说,Connect和ConnectionRequest事件只是发生在连接之初的,连接成功后就不会再发生了。
而DataArrival是发生在每次接收到数据时,A发送,到达B处,那么B就会发生DataArrival;B发送,到达A处,那么A就会发生DataArrival。
而那个ConnectionRequest,是在连接还没建立前,一方发出连接请求,另一方发生ConnectionRequest,它只会发生在被请求的一方。
不明白楼主怎么会对这几个事件纠缠不清。
[解决办法]
学习
[解决办法]
hao 联
[解决办法]
不太敢相信,那是商用代码...

ConnectionRequest是服务端握手确认的步骤,握手步骤是不应该破坏的,蓄意破坏用在这里常是属于flood的做法...

发送就不该是在握手过程调用的.因为一旦服务端忙,返回的是异常,那么数据就丢了,再者说这样的处理方式对于报文处理来说也不合理

后期维护人员会告诉客户,这是你们网络不稳定..丢包...
[解决办法]
ConnectionRequest我觉得就已经是连接建立了,只不过是给他分配本地的操作端口
[解决办法]

探讨
ConnectionRequest我觉得就已经是连接建立了,只不过是给他分配本地的操作端口

------解决方案--------------------


顶,学习,路过....................
[解决办法]
在大规模使用winsock的情况下,服务器端sock控件往往以数组形式出现,也就是说同一个sock控件会响应来自不同客户端的请求,而每个请求,服务器在接收后,都会进行一系列的处理(此时客户端state永远不会为7),然后才会响应客户端。也就是说如果服务器端在处理某个通道的逻辑时,发现了意外,那么此时此通道的客户端代码将变成死循环,可能你会说那是你服务器端代码写的不好,跟客户端代码没关系,但对于每个有点职业道德的程序员来讲,是不能够让自己的代码出现死循环的(这里指的是所有的商业代码) 

用一个端口进行监听,服务器在处理来自客户端的请求后,接受并丢给其他端口进行连接,然后监听端口就会空闲,就算是某个通道锁死也不会影响其他用户的正常连接。而且,服务端接收到来自客户端的连接,如果在规定时间内没有连接成功。那会出现超时错误。。那么那个时候可以释放资源,也不会很容易的造成锁死。。,,我的见解是这样。。请大虾们赐教。。偶小菜一个。
[解决办法]
用HTTP方式获取IP和端口后,移交给WINSOCK会不会改变?
[解决办法]
学习学习。
[解决办法]
我说一下自己所理解的,有不对的地方欢迎朋友们指正:

一个典型和完整的服务端客户端程序是这样工作的:
1、服务端以约定的端口进行监听,即
wskServer.localport=123
wskServer.Listen
此时wskServer的state=2
2、客户端以约定的端口连接服务端,即
wskClient.remotehost="xxx.xxx.xxx.xxx"
wskClient.remoteport=123
wskClient.Connect
注意,只要执行Connect方法,那么无论这次连接服务端如何响应,客户端都会发生wskClient_Connect()事件,而且wskClient的state会等于7
3、服务端接到客户端的连接请求,会发生wskServer_ConnectionRequest事件,在这个事件中服务端可以选择如何处理这个连接请求:
a:如果服务端对这个请求不理睬,那么本次连接失败,客户端会发生一个wskClient_close()事件,而且wskClient的state=8,必须重新close以后才能再次发起连接;而服务端wskServer的state一直是2即监听状态;
b:如果服务端要允许这次请求,那么它必须先close自己然后accept客户端的requestID,它的state会由2变为0再变为7,这时客户端和服务端才真正建立起连接。值得注意的是:服务端做Accept这个动作,在服务端和客户端不会发生任何事件,只会引起wskServer的state的改变!
4、连接建立后,就可以相互发送数据了,任何一端SendData后会发生一个SendComplete事件,而接到数据的一端会发生一个DataArrival事件,在该事件中用getdata取出数据进行处理就行了;
5、任务完成后,任何一端都可以用close方法来结束这次连接,比如客户端wskClient.close,那么它会发生wskClient_Close()事件,state会由7变成0,服务端也会同时发生wskServer_close()事件,但是它的state则会由7变为8,它必须close以后重新进行监听,等待客户端的再次连接。

以上就是一次完整连接的过程,可以看出来,之所以有很多人选择在ConnectionRequest()事件中作出响应并发送数据,基本上是没有更好的办法的,比如说一个聊天程序,客户端上线后服务端需要发送一句友好的问候语,那么你怎么办?选择只有ConnectionRequest()事件!

Winsock确实有很多令人费解的地方,比如我还真想不出这个Connect()事件有什么用,因为它只发生在发起连接的一端,而且不管对方是否允许,呵呵。。。
[解决办法]
这个东西我也不是很清楚,就看过一点TCP祥解。
我的看法是:
CONNECT是主动方在发起连接,需要根据返回才能确认是否能够建立连接
而CONNECTREQUEST是服务器方在收到客户端的连接请求后,给上层应用程序的一个事件,通过它告诉操作系统是否接受连接请求。
LZ的看法我个人认为是混淆了客户端和服务端对建立TCP的连接处理方式,因为对C++没什么了解,不对的地方请指出,多多包涵。
[解决办法]
向楼主学习!
[解决办法]

探讨
Winsock确实有很多令人费解的地方,比如我还真想不出这个Connect()事件有什么用,因为它只发生在发起连接的一端,而且不管对方是否允许,呵呵。。。

[解决办法]
学习中....
[解决办法]
学习!
[解决办法]
好贴,希望多多探讨,我等多多受益
[解决办法]
我接着开心海的说哈:首先异地执行了connect方法 接收方wskClient_Connect()事件不一定被会触发, 
能够肯定的是会被触发wskServer_ConnectionRequest()事件,公当state=7时,connect事件才会生效(至于是不是这样请大家做海量测试,不仅仅测试本地) 
支持这个观点。
[解决办法]
学习了!

热点排行