两个测试:
1. 单线程, connect结合select超时连接50个一样的IP, 结果很正常, 50次select都没返回错误.
2. 多线程, connect结合select超时连接50个一样的IP, 开50个线程, 每个线程负责一个连接, 就会出现问题, 有些可以正常返回, 有些select会返回超时, 超时值设得很大也不行.请问是为什么, select在多个线程同时处于socket等待的时候是如何工作的?
1. 单线程, connect结合select超时连接50个一样的IP, 结果很正常, 50次select都没返回错误.
2. 多线程, connect结合select超时连接50个一样的IP, 开50个线程, 每个线程负责一个连接, 就会出现问题, 有些可以正常返回, 有些select会返回超时, 超时值设得很大也不行.请问是为什么, select在多个线程同时处于socket等待的时候是如何工作的?
解决方案 »
- rss阅读器
- 删除graph中的所有filter,IEnumFilters Reset()出错!
- 几个基础问题 谢谢
- VC++6能不能在win2003系统下安装
- 用的ODBC来更新数据库,CTime类型字段变量,第一次更新成功,第二次就OVER了,但又没有错误信息,只有一个大红插
- 请教各位高手,怎么用c++语言编写打印如下空心菱形图形的程序?
- 怎么改变Static控件的窗口风格?(急)
- 谁能提供install shield6.22的汉化版或汉化补丁、教程也可以?
- 如何使单文档程序开始运行时自动打开上次运行的文档,帮帮忙,保证给高分!
- 关于GETDLGITEM()的问题
- 一个用户只允许连续回复3次
- UDP 打洞的问题!
#include <stdio.h>
#include <windows.h>#pragma comment(lib, "ws2_32")long lCount = 0;
long lThreadCount = 0;DWORD _stdcall proc(LPVOID lParam)
{
for (long i = 0; i < lThreadCount; i++)
{
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); u_long ul = 1;
ioctlsocket(s, FIONBIO, &ul); sockaddr_in addr = {0};
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(135);
int iret = connect(s, (sockaddr*)&addr, sizeof(addr)); fd_set wfds = {0};
FD_SET(s, &wfds);
timeval timeout = {0};
timeout.tv_sec = 3; // 3秒超时
iret = select(0, NULL, &wfds, NULL, &timeout); if (0 == iret)
{
printf("select timeout\n");
}
else if (0 > iret)
{
printf("select error\n");
}
else
{
printf("%d\n", ++lCount);
} closesocket(s);
} return 0;
}void single()
{
lThreadCount = 500;
CloseHandle(CreateThread(NULL, 0, proc, NULL, 0, NULL));
}void multiple()
{
lThreadCount = 1;
for (int i = 0; i < 500; i++)
{
CloseHandle(CreateThread(NULL, 0, proc, NULL, 0, NULL));
}
}void main()
{
WSADATA lpWSAData;
WSAStartup(0x0202, &lpWSAData); //single();
multiple(); while (1);
}不知道这样测试对不对
可以把所有socket都放在fd_set里, 一起select咋。
把timeout.tv_sec = 3; // 3秒超时 设置再短一点呢?
而你在connect之后直接select,当然会出问题
==============
可是延时设很大结果也是一样啊.
必然超时的意思是:即使在select操作阻塞期间,connect成功了,select也不会成功
其实这只是一个测试, 用本机的测试, 如果说上面是500个连接连同一台机有问题,但在实际应用的只是3,4十个连接, 而且是不同的IP,这个应该是不存在服务端响应慢的原因吧,但一样会会出现上述问题, 单线程逐一连接全部成功,而且connect返回很快,不会有什么延时, 但在多线程的时候, 设几十秒的延时也同样是失败!
否则,返回超时,即使你超时时间设置成一年也没用
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吧.
多线程应该用阻塞模式,建议去掉这句,然后做一个大的循环,多线程的和单线程的不能用同一个线程函数,
还有楼主创建多线程的方法是不对的,应该在循环创建的时候加一个小延时,比方说Sleep(100)
说明select能否成功与connect是否已成功是互相关联的!如果异步connect还没成功,select就一定不会成功
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集合中
CreateThread ,不一定创建thread就立即运行并成功返回HANDLE , 为什么立即关闭?
线程运行完成了?你去查看下MSDN吧?把所有的代码分开
检测所有的返回值,别想当然
while (1); ???? 干什么用?
死循环?
晕,异步connect是立即返回的,通常都返回SOCKET_ERROR,且GetLastError()=WSAEWOULDBLOCKTCP协议下调用select时首会先去查询socket是否已握手,若尚未握手,select不会试图等待connect完成,它会直接返回超时;若socket已握手,然后才会去查询socket是否被其他操作block中,这时候select才会根据超时参数进行等待所以MSDN才会说,select可以用来判断connect是否已经完成你调用异步connect后马上调用select,则select查询握手状态时,connect既可能刚刚完成了,也可能还未完成,所以你的select可能成功,也可能失败,就这么简单,和你设不设置超时没有关系
未完成,所以你的select可能成功,也可能失败,就这么简单,和你设不设置超时没有关系
==================如果select在connect后去查询它是否握手成功, "若尚未握手,select不会试图等待connect完成,它会直
接返回超时", 似乎不管怎样都不太可能会成功吧, 因为网络是有延时的, 那select岂不是每次都失败? 但同
样是connect后马上调用select, 为什么单线程又全部都成功呢? 如果调用select的时候, 就能确定已经
connect成功了, 那还要select的延时来干什么呢, select这里的效果不是sleep, 而是判断socket在延时
期间是否connect成功啊
楼主报名吧!你得搞清楚select模型再试验啊呵呵
====================
单线程很快, 是因为这是本机测试, 但是实际实用也有慢的情况, 一样都会全部成功!(单线程)
异步connect返回也是WSAEWOULDBLOCK, select也会尝试去等待吧? 而且测试结果也表明, select并不是
马上就返回, 而是超时时间过后才返回的. 更奇怪的是, 只要有一个超时, 后面跟着的就会全部超时, 比如第
20个线程超时了, 那么第21个线程连接的即使是本机IP, 也会超时.(多线程)
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);不是猜测, 错误码早就看过了, select返回0是超时, 此时GetLastError是0, 操作成功完成