关于Socket的一个非常简单的问题(EventSelect模型的)

sxbyl 2002-11-14 09:54:47
我的一个程序用了WSAEventSelect,模型,发现无法正常工作:
我的Event是用WSACreateEvent建立的,步骤如下:
1、WSAEventSelect(m_hSocket,m_hWaitEvents[0],FD_WRITE | FD_CLOSE)选择事件,
2、WSAWaitForMultipleEvents(sizeof(m_hWaitEvents)/sizeof(HANDLE), m_hWaitEvents,FALSE,m_dwTimeout,FALSE);等待事件
3、WSAEnumNetworkEvents(m_hSocket,m_hWaitEvents[0],&we);判断事件类型
4、send(m_hSocket,(const char *)pData+nSentSize,nSize-nSentSize,0);发送数据
然后我发现下一轮中与Socket相关联的Event再也无法被激活了,非常奇怪!谁能告诉我是那里出了问题啊!急!谢谢了!
...全文
166 31 打赏 收藏 转发到动态 举报
写回复
用AI写文章
31 条回复
切换为时间正序
请发表友善的回复…
发表回复
Bind 2002-11-18
  • 打赏
  • 举报
回复
返回整个BUFFER的长度是一种理想状态。不妨在拨号的环境下调试绝对会出现返回值小于BUFFER长度的情况出现。所以分段处理是必要的。
JJONY 2002-11-18
  • 打赏
  • 举报
回复
对于send返回发送数据的大小的这个问题, 我也感到很困惑, 它要不就WSAWOULDBLOCK,要不就是整个数据区的大小。好像没必要我们去进行数据分段了。但我又想send是从unix系统继承过为的东西,微软也说过unix上开发的这种通信程序在理论上是可以不用修改就能移植到Windows上的。那么windows上的一套winsock函数都是与unix的一模一样。可能在unix系统blocking状态下的socket在send时就会有返回一部分数据区长度的机会,需要进行分段处理。但在Windows异步机制下的socket send始终是整个数据区大小或WSAWOULDBLOCK。

以上是只是我的猜测,反正我做程序时都进行了分段处理了。
JJONY 2002-11-18
  • 打赏
  • 举报
回复
呵呵,16M?是的,send真的把16M“一次”发出去了,不知道你用的机器是不是2000, 如果是的话可以细心的看看system tray里你的网络适配器的状态,它应该是不继地亮着的也就是说你的send正在发送数据。
当你用send发送数据时,winsock dll会新建一个thread为你进行数据的发送操作,一次把16M的数据投到send里头,thread就会一点点的慢慢发,但send就马上返回,如果你再一次send的话,应该你会收到WSAWOULDBLOCK的错误,因为winsock(不是TCP/IP传输层)的thread还没发完啊,发完后才会收到FD_WRITE。
在用DEBUG版本的程序结束运行后没发现在output里的thread exit code 多了好几个吗?
Bind 2002-11-18
  • 打赏
  • 举报
回复
讨论这个问题就比较难了。不管send内部如何操作,我们只需关心它的返回值就行了。总之大于0就是发送成功小于0就是失败。
sxbyl 2002-11-18
  • 打赏
  • 举报
回复
MSDN上说异步send如果成功的话,返回值在1-max size之间,也就是说,send内部应该没有那个循环来保证所有的数据全部发送出去
Bind 2002-11-18
  • 打赏
  • 举报
回复
发送是这样做的:把数据从你的缓冲中拷贝到SOCKET缓冲再发送。如果你的数据太大了,当然要分几次拷贝了。我猜里面是有一个FOR循环式的操作。
sxbyl 2002-11-18
  • 打赏
  • 举报
回复
我一次send 16M的数据包,半秒内就给我成功返回了,这么短的时间内数据肯定是发不完,那当然是方缓冲里了
Bind 2002-11-18
  • 打赏
  • 举报
回复
哪有一次放啊?每次把一部分放入SOCKET缓冲中。大小不超过缓冲区的最大长度。这怎么会撑死呢?
sxbyl 2002-11-18
  • 打赏
  • 举报
回复
这个我当然知道,还可以通过设置那个LINGER标志来设定这个选项,只是奇怪系统为什么要把那么大的数据块全部放到缓冲里,不怕撑死啊
Bind 2002-11-18
  • 打赏
  • 举报
回复
你的担心有点多余了。TCP/IP是支持从容关闭的。在发送方发出关闭请求后,接收方会把未接收完的数据继续接收完再响应这个关闭消息。
sxbyl 2002-11-18
  • 打赏
  • 举报
回复
虽然对计算机来说是小菜一碟,不过对于我那可怜的10M网绝对的是大菜啊,而且我的服务程序关闭之后客户端可以继续接收数据~
Bind 2002-11-18
  • 打赏
  • 举报
回复
大概你的计算机太好了吧!数据量虽然很大,但是对计算机来说还是小菜一碟啊!如果你不放心,不妨用工具观察一下你的程序的内存情况。在发送大数据时是否有内存占用突然增大的现象。按照你的想法数据未被发出,那么不管怎么样总是需要一个地方来暂存它的对吧。要是内存使用并未增大那么毫无疑问数据一定是发出去了的。
sxbyl 2002-11-18
  • 打赏
  • 举报
回复
To:Bind(天高云淡)
那么短的时间不可能全发出去的,我用的是10M网,16M的数据不可能在不到1秒的时间内全部发送出去。而且send返回的也不是什么WSAWOULDBLOCK,而是那16M数据的大小 !!
Bind 2002-11-18
  • 打赏
  • 举报
回复
发出去了啊!在SEND未返回SOCKET_ERROR之前,所有的数据发送都是正常的。

windows网络编程是这样解释的:
将一个套接字置为非锁定模式之后,WINSOCK API调用会立即返回。在大多数情况下,这些调用都会“失败”,并返回一个WSAWOULDBLOCK错误。什么意思呢?它意味着请求的操作在调用期间没有时间完成。

又:若应用程序针对一个套接字调用了WSAASYNCSELECT,那么套接字的模式会从“锁定”自动变成非锁定。
sxbyl 2002-11-18
  • 打赏
  • 举报
回复
我就是想知道我发16M的数据包他立即返回后那16M的数据放哪里去了
yanhuahui 2002-11-18
  • 打赏
  • 举报
回复
socket就是tcp层的接口。同时发10M我没试过,单独发30M我成功实验过。
sxbyl 2002-11-18
  • 打赏
  • 举报
回复
我用的是2000
关于JJONY() 的猜测:当你用send发送数据时,winsock dll会新建一个thread为你进行数据的发送操作。socket应该不会再去建线程了吧?那样一个send还要再建一个线程开销太大了,不过系统应该是把它放到一个缓冲里了,我很奇怪系统为什么要这么处理
JJONY 2002-11-18
  • 打赏
  • 举报
回复
没有啊,我的程序就是在拨号环境下调试的。我的程序运行环境是2000 prof,

是不是,2000 下就不用分段。
ttzzgg_80713 2002-11-17
  • 打赏
  • 举报
回复
WSAEnumNetworkEvents之后要清除网络事件。下次要用重新设置吧。
sxbyl 2002-11-17
  • 打赏
  • 举报
回复
To:yanhuahui(小辉)
你说的是TCP层的,我说的是socket层的,两回事。socket还可以不设缓冲,TCP层总不能没有缓冲吧。tcp给自己分配空间总有个限度吧?我如果很多socket同时发送16M的数据包,难道他还都满足啊?

To:ttzzgg_80713(别欺侮我)
WSAEnumNetworkEvents就有reset的功能了。我的园子早停了,现在虽然也有宽带,不过机子上装的是professional,没法运行SQL和正规的IIS
加载更多回复(11)

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧