select多线程的问题

mscrack 2009-07-31 04:08:48
两个测试:
1. 单线程, connect结合select超时连接50个一样的IP, 结果很正常, 50次select都没返回错误.
2. 多线程, connect结合select超时连接50个一样的IP, 开50个线程, 每个线程负责一个连接, 就会出现问题, 有些可以正常返回, 有些select会返回超时, 超时值设得很大也不行.

请问是为什么, select在多个线程同时处于socket等待的时候是如何工作的?
...全文
1005 32 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
32 条回复
切换为时间正序
请发表友善的回复…
发表回复
xwsn007 2009-08-06
  • 打赏
  • 举报
回复
mark 顶!
gotooker 2009-08-06
  • 打赏
  • 举报
回复
奥,那应该是并发的链接过多造成的。listen(m),监听队列设置的值过小。
mscrack 2009-08-05
  • 打赏
  • 举报
回复
[Quote=引用 28 楼 animalgogogo 的回复:]
问个问题WSAAsynSelet函数注册的事件怎么注销啊。
[/Quote]
MSDN:
To cancel all notification indicating that Windows Sockets should send no further messages related to network events on the socket, lEvent is set to zero.

rc = WSAAsyncSelect(s, hWnd, 0, 0);

[Quote=引用 29 楼 gotooker 的回复:]
照你的程序select是成功了返回,失败了肯定是超时,你可以超时的时候WSAGetLastError()分析一下错误码,这样一味乱猜没什么意思
[/Quote]
不是猜测, 错误码早就看过了, select返回0是超时, 此时GetLastError是0, 操作成功完成
gotooker 2009-08-05
  • 打赏
  • 举报
回复
照你的程序select是成功了返回,失败了肯定是超时,你可以超时的时候WSAGetLastError()分析一下错误码,这样一味乱猜没什么意思
animalgogogo 2009-08-05
  • 打赏
  • 举报
回复
问个问题WSAAsynSelet函数注册的事件怎么注销啊。
mscrack 2009-08-05
  • 打赏
  • 举报
回复
1、单线程的connect很快就会成功,多线程并发的connect会受服务器相应能力的影响,不见得能很快成功

2、select不仅仅是用在connect之后的,其他IO操作(recv、send等)之后也可能调用select,这时候select的超时参数就会起作用,因为socket是握手状态中,只是block了而已,select就会尝试等待
====================
单线程很快, 是因为这是本机测试, 但是实际实用也有慢的情况, 一样都会全部成功!(单线程)
异步connect返回也是WSAEWOULDBLOCK, select也会尝试去等待吧? 而且测试结果也表明, select并不是
马上就返回, 而是超时时间过后才返回的. 更奇怪的是, 只要有一个超时, 后面跟着的就会全部超时, 比如第
20个线程超时了, 那么第21个线程连接的即使是本机IP, 也会超时.(多线程)
mscrack 2009-08-04
  • 打赏
  • 举报
回复
TCP协议下调用select时首会先去查询socket是否已握手,若尚未握手,select不会试图等待connect完成,它会直接返回超时;若socket已握手,然后才会去查询socket是否被其他操作block中,这时候select才会根据超时参数进行等待

所以MSDN才会说,select可以用来判断connect是否已经完成

你调用异步connect后马上调用select,则select查询握手状态时,connect既可能刚刚完成了,也可能还
未完成,所以你的select可能成功,也可能失败,就这么简单,和你设不设置超时没有关系
==================

如果select在connect后去查询它是否握手成功, "若尚未握手,select不会试图等待connect完成,它会直
接返回超时", 似乎不管怎样都不太可能会成功吧, 因为网络是有延时的, 那select岂不是每次都失败? 但同
样是connect后马上调用select, 为什么单线程又全部都成功呢? 如果调用select的时候, 就能确定已经
connect成功了, 那还要select的延时来干什么呢, select这里的效果不是sleep, 而是判断socket在延时
期间是否connect成功啊
bylea 2009-08-04
  • 打赏
  • 举报
回复
[Quote=引用楼主 mscrack 的回复:]
两个测试:
1. 单线程, connect结合select超时连接50个一样的IP, 结果很正常, 50次select都没返回错误.
2. 多线程, connect结合select超时连接50个一样的IP, 开50个线程, 每个线程负责一个连接, 就会出现问题, 有些可以正常返回, 有些select会返回超时, 超时值设得很大也不行.

请问是为什么, select在多个线程同时处于socket等待的时候是如何工作的?
[/Quote]

方法问题.........................
1,所以的连接都是顺序的,不存在另一端处理不完的情况.
2,所以的连接都是"并发"的,另一端存在部分连接无法完成的情况,或已经达到最大连接数,(解决方法:重试几次).
另:网络资源紧张也有可能造成连接无法完成(你这里好像不存在).
teleinfor 2009-08-04
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 cactus12345 的回复:]
网络编程开发培训, 采用1对1教学, 致力于把初学者培养成为一位, 能熟练使用c++开发工具在window平台下, 开发c/s构架的网络应用系统. 我将根据各人的不同情况, 制定一套有效的学习进度.  具体情况,可以联系 qq: 646810840.
[/Quote]

楼主报名吧!你得搞清楚select模型再试验啊。。。呵呵。。。
fangle6688 2009-08-04
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 mscrack 的回复:]
TCP协议下调用select时首会先去查询socket是否已握手,若尚未握手,select不会试图等待connect完成,它会直接返回超时;若socket已握手,然后才会去查询socket是否被其他操作block中,这时候select才会根据超时参数进行等待

所以MSDN才会说,select可以用来判断connect是否已经完成

你调用异步connect后马上调用select,则select查询握手状态时,connect既可能刚刚完成了,也可能还
未完成,所以你的select可能成功,也可能失败,就这么简单,和你设不设置超时没有关系
==================

如果select在connect后去查询它是否握手成功, "若尚未握手,select不会试图等待connect完成,它会直
接返回超时", 似乎不管怎样都不太可能会成功吧, 因为网络是有延时的, 那select岂不是每次都失败? 但同
样是connect后马上调用select, 为什么单线程又全部都成功呢? 如果调用select的时候, 就能确定已经
connect成功了, 那还要select的延时来干什么呢, select这里的效果不是sleep, 而是判断socket在延时
期间是否connect成功啊

[/Quote]


1、单线程的connect很快就会成功,多线程并发的connect会受服务器相应能力的影响,不见得能很快成功

2、select不仅仅是用在connect之后的,其他IO操作(recv、send等)之后也可能调用select,这时候select的超时参数就会起作用,因为socket是握手状态中,只是block了而已,select就会尝试等待
fangle6688 2009-08-03
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 mscrack 的回复:]
u_long ul = 1;
ioctlsocket(s, FIONBIO, &ul);

int iret = connect(s, (sockaddr*)&addr, sizeof(addr)); //iret值确实不为0啊, 表示没成功吧

fd_set wfds = {0};
FD_SET(s, &wfds);
timeval timeout = {0};
timeout.tv_sec = 3; // 3秒超时
iret = select(0, NULL, &wfds, NULL, &timeout); //但是select会成功

select设置延时的作用不就是返回只要在用户设置的延时期间内有响应的socket, 它都会过滤在对应的子集内吗?
select能判断异步connect成功, 并不表示connect马上成功吧, 只要connect在设置的延时内有回应,
select都会被它放到wfds集合中
[/Quote]

晕,异步connect是立即返回的,通常都返回SOCKET_ERROR,且GetLastError()=WSAEWOULDBLOCK

TCP协议下调用select时首会先去查询socket是否已握手,若尚未握手,select不会试图等待connect完成,它会直接返回超时;若socket已握手,然后才会去查询socket是否被其他操作block中,这时候select才会根据超时参数进行等待

所以MSDN才会说,select可以用来判断connect是否已经完成

你调用异步connect后马上调用select,则select查询握手状态时,connect既可能刚刚完成了,也可能还未完成,所以你的select可能成功,也可能失败,就这么简单,和你设不设置超时没有关系
mscrack 2009-08-03
  • 打赏
  • 举报
回复
似乎跟这些没有关系吧
danscort2000 2009-08-03
  • 打赏
  • 举报
回复
CloseHandle(CreateThread(NULL, 0, proc, NULL, 0, NULL));

能这么写吗?
CreateThread ,不一定创建thread就立即运行并成功返回HANDLE , 为什么立即关闭?
线程运行完成了?你去查看下MSDN吧?

把所有的代码分开
检测所有的返回值,别想当然


while (1); ???? 干什么用?
死循环?

pady_pady 2009-08-03
  • 打赏
  • 举报
回复
ioctlsocket(s, FIONBIO, &ul);
多线程应该用阻塞模式,建议去掉这句,然后做一个大的循环,多线程的和单线程的不能用同一个线程函数,
还有楼主创建多线程的方法是不对的,应该在循环创建的时候加一个小延时,比方说Sleep(100)
mscrack 2009-08-03
  • 打赏
  • 举报
回复
u_long ul = 1;
ioctlsocket(s, FIONBIO, &ul);

int iret = connect(s, (sockaddr*)&addr, sizeof(addr)); //iret值确实不为0啊, 表示没成功吧

fd_set wfds = {0};
FD_SET(s, &wfds);
timeval timeout = {0};
timeout.tv_sec = 3; // 3秒超时
iret = select(0, NULL, &wfds, NULL, &timeout); //但是select会成功

select设置延时的作用不就是返回只要在用户设置的延时期间内有响应的socket, 它都会过滤在对应的子集内吗?
select能判断异步connect成功, 并不表示connect马上成功吧, 只要connect在设置的延时内有回应,
select都会被它放到wfds集合中
fangle6688 2009-08-03
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 mscrack 的回复:]
MSDN的意思会不会是指connect成功后, select会把socket过滤在writefds中, 而不是指connect成功后才调用select呢?
connect的函数说明是中也指出,
With a nonblocking socket, the connection attempt cannot be completed immediately. In this case, connect will return SOCKET_ERROR, and WSAGetLastError will return WSAEWOULDBLOCK. In this case, there are three possible scenarios:

Use the select function to determine the completion of the connection request by checking to see if the socket is writeable

这个也不是在connect成功后用select吧.
[/Quote]


select为什么可以用来判断异步connect是否已成功?
说明select能否成功与connect是否已成功是互相关联的!

如果异步connect还没成功,select就一定不会成功
fangle6688 2009-08-02
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 mscrack 的回复:]
当异步connect还没有实际成功时,调用select必然超时
==============
可是延时设很大结果也是一样啊.
[/Quote]

必然超时的意思是:即使在select操作阻塞期间,connect成功了,select也不会成功
mscrack 2009-08-02
  • 打赏
  • 举报
回复
设置超时长点, 是针对服务端响应会较慢, 慢它也有返回吧, 可是设超时大点为什么select还是不成功呢?
其实这只是一个测试, 用本机的测试, 如果说上面是500个连接连同一台机有问题,但在实际应用的只是3,4十个连接, 而且是不同的IP,这个应该是不存在服务端响应慢的原因吧,但一样会会出现上述问题, 单线程逐一连接全部成功,而且connect返回很快,不会有什么延时, 但在多线程的时候, 设几十秒的延时也同样是失败!
mscrack 2009-08-02
  • 打赏
  • 举报
回复
MSDN的意思会不会是指connect成功后, select会把socket过滤在writefds中, 而不是指connect成功后才调用select呢?
connect的函数说明是中也指出,
With a nonblocking socket, the connection attempt cannot be completed immediately. In this case, connect will return SOCKET_ERROR, and WSAGetLastError will return WSAEWOULDBLOCK. In this case, there are three possible scenarios:

Use the select function to determine the completion of the connection request by checking to see if the socket is writeable

这个也不是在connect成功后用select吧.
mscrack 2009-08-02
  • 打赏
  • 举报
回复
connect成功是什么意思? 异步connect怎么会立刻返回成功呢? 单线程也不是马上返回成功的吧. 但单线程工作得很好.
加载更多回复(10)

18,363

社区成员

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

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