多线程connect问题

elichen9 2011-12-14 03:34:03
最近做测试发现了这样一个问题,创建20条线程去不断连接服务端,其中只有一个IP地址是存在的,问题来了,如果值创建一条线程来连接存在的IP,那是没有问题的,但是创建了20条线程后,存在的那个IP connect也连接失败,这是为什么呢?
(我这边在192.168.1.22的机子上有一个服务端)
//main.c
#include <winsock2.h>
#include <stdio.h>
#include <process.h>

#include <errno.h>
#pragma comment(lib,"ws2_32.lib")

#include <stdlib.h>
#include <string.h>

#define PORT 80

int InitSock(void)
{
int err = 0;
WORD wVersionRequested;
WSADATA wsaData;

wVersionRequested = MAKEWORD( 2, 2 );

err = WSAStartup(wVersionRequested, &wsaData);
if ( err != 0 )
{
return -1;
}
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 )
{
WSACleanup();
return -1;
}

return 0;
}

int Hi_Setup_OpenTcp(struct sockaddr *SockAddr, int NameLen, int nTimeout)
{
int f = -1;
struct timeval tv;
fd_set writefds;
int len, error, s32Ret;
unsigned long non_blocking = 1;
unsigned long blocking = 0;
unsigned long reuse = 1;

if ((f = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
return -1;
}

tv.tv_sec = nTimeout / 1000;
tv.tv_usec = nTimeout % 1000;

ioctlsocket(f, FIONBIO, &non_blocking);

s32Ret = connect(f, SockAddr, NameLen);
if (s32Ret < 0)
{
FD_ZERO(&writefds);
FD_SET((unsigned int)f, &writefds);
if(select(f+1, NULL, &writefds, NULL, &tv) != 0)
{
if(FD_ISSET(f, &writefds))
{
len = sizeof(error);
//下面的一句一定要,主要针对防火墙
if(getsockopt(f, SOL_SOCKET, SO_ERROR, (char *)&error, &len) < 0)
goto error_ret;
if(error != 0)
goto error_ret;
}
else
goto error_ret; //timeout or error happen
}
else
goto error_ret;

ioctlsocket(f, FIONBIO, &blocking);
}
else
{
error_ret:
closesocket(f);
return -1;
}

return f;
}

/******************************************
* connect server
******************************************/
int HI_Setup_Connect(const char* pServer, int nPort, int nTimeout,
int *pSessSock)
{
int GetHost = -1;
struct sockaddr_in SockAddr;
unsigned int net_addr = 0;
struct hostent *Hostent = NULL;

Hostent = gethostbyname(pServer);
if (NULL != Hostent)
{
GetHost = 0;
}
else
{
net_addr = inet_addr(pServer);
if(INADDR_NONE == net_addr)
{
GetHost = -1;
}
else
{
Hostent = gethostbyaddr((const char*) &net_addr, sizeof(unsigned int), PF_INET);
if (Hostent)
{
GetHost = 0;
}
}
}

if (0 == GetHost)
{
SockAddr.sin_family = AF_INET;
SockAddr.sin_addr.s_addr = *(unsigned int *) Hostent->h_addr;
SockAddr.sin_port = htons(PORT);
*pSessSock = Hi_Setup_OpenTcp((struct sockaddr *) & SockAddr,
sizeof(SockAddr), nTimeout);

//if(strcmp(pServer, "192.168.1.22") == 0)
// printf("%s\n", pServer);
if (*pSessSock < 0)
{
GetHost = -1;
}
}
return GetHost;

}

char sHost[20][32] = {"192.168.1.22", "192.168.1.200",
"192.168.1.201", "192.168.1.202",
"192.168.1.203", "192.168.1.204",
"192.168.1.205", "192.168.1.206",
"192.168.1.207", "192.168.1.208",
"192.168.1.209", "192.168.1.210",
"192.168.1.211", "192.168.1.212",
"192.168.1.213", "192.168.1.214",
"192.168.1.215", "192.168.1.216",
"192.168.1.217", "192.168.1.218"};

int ConnectPross(int index)
{
printf("%s\n", sHost[index]);
while(1)
{
int nSock = -1;
int ret = HI_Setup_Connect(sHost[index], PORT, 5000, &nSock);
if(ret == -1)
{
if(index == 0)
{
printf("connect Fail:%s\n", sHost[index]);
}
}
else
{
closesocket(nSock);
if(index == 0)
{
printf("connected\n");
}
}

Sleep(5000);
}
return 0;
}

DWORD WINAPI ConnectThreadPross(LPVOID lpParameter)
{
int index = (int)lpParameter;
ConnectPross(index);
return 0;
}

int main(int argc, char* argv[])
{
int i = 0;
DWORD dwThreadID = 0;
HANDLE hThread = NULL;

InitSock();
for(i=0; i<20; i++)
{
dwThreadID = 0;
hThread = CreateThread(NULL, 0, ConnectThreadPross, (LPVOID)i, 0, &dwThreadID);
CloseHandle(hThread);
Sleep(10);
}

while(1)
{
Sleep(1000);
}

WSACleanup();
return 0;
}
...全文
119 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2011-12-16
  • 打赏
  • 举报
回复
用Process Explorer可以
找出进程打开了哪些文件、注册表项和其他对象,已加载哪些 DLL 等信息。这个功能异常强大的实用工具甚至可以显示每个进程的所有者。
http://www.microsoft.com/china/technet/sysinternals/utilities/ProcessExplorer.mspx
赵4老师 2011-12-16
  • 打赏
  • 举报
回复
检查是否资源泄漏的办法之一:
在任务管理器 进程 查看 选择列 里面选择:内存使用、虚拟内存大小、句柄数、线程数、USER对象、GDI对象
让你的程序(进程)不退出,循环执行主流程很多遍,越多越好,比如1000000次甚至无限循环,记录以上各数值,再隔至少一小时,越长越好,比如一个月,再记录以上各数值。如果以上两组数值的差较大或随时间流逝不断增加,则铁定有对应资源的资源泄漏!
赵4老师 2011-12-16
  • 打赏
  • 举报
回复
操作系统底层每创建和销毁一个socket都是需要一定时间的。
elichen9 2011-12-14
  • 打赏
  • 举报
回复
没有人遇到过这样的问题吗?
elichen9 2011-12-14
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 seagate_64 的回复:]
线程里加入InitSock();WSACleanup();试一下
[/Quote]
还是一样!!!!!!
Seagate_64 2011-12-14
  • 打赏
  • 举报
回复
线程里加入InitSock();WSACleanup();试一下
elichen9 2011-12-14
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 zhao4zhong1 的回复:]
请检查所有函数的返回值。
[/Quote]
返回值没有问题的,最郁闷的是的如果跑久了,电脑连接网络会变得相当慢,有时候网卡直接堵死,关掉软件又ok
赵4老师 2011-12-14
  • 打赏
  • 举报
回复
请检查所有函数的返回值。

64,646

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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