急, 一个线程池(自编)与网络SOCKET的程序,STL的代码发生问题,那位大虾帮帮忙

wujian53 2004-08-31 04:46:08
//线程池(自编)
#ifndef _THREAD_POOL_H_
#define _THREAD_POOL_H_
#pragma warning(disable: 4530)
#pragma warning(disable: 4786)
#include <cassert>
#include <vector>
#include <queue>
#include <cstdio>
using namespace std;
#include <windows.h>
#include <process.h>

class thread_pool
{
protected:

static DWORD WINAPI work_proc(LPVOID lpParameter = NULL);//工作线程

struct work_item; //工作数据结构
struct thread_item; //线程数据结构
queue<work_item *> _work_queue; //工作队列
vector<thread_item *> _threads;//线程数据
CRITICAL_SECTION _cs_work_queue, _cs_threads; //工作队列临界, 线程数据临界
HANDLE _event_end, _event_complete, _semaphore_call;//结束事件, 完成事件, 工作信号
long _thread_num, _runing_num; //线程数, 运行的线程数

void add(int num)//添加线程
{
EnterCriticalSection(&_cs_threads);
for(int _i=0, i; _i<num; _i++)
{
i = _i + _thread_num;
_threads.push_back(new thread_item( this));
_threads[i]->_handle = CreateThread(NULL, 0, work_proc, _threads[i], 0, &(_threads[i]->_thread_id));
assert(_threads[i]->_handle);
}
_thread_num += num;
LeaveCriticalSection(&_cs_threads);
}

public:

struct work_item
{
void (*_fun)(void *);//用户函数
void *_para; //用户参数
work_item(void (*fun)(void *) = NULL, void *para = NULL) : _fun(fun), _para(para)
{ };
};

struct thread_item
{
unsigned long _thread_id; //线程ID
HANDLE _handle; //线程句柄
thread_pool* _this; //线程池的指针
thread_item(thread_pool *pthis) : _this(pthis), _handle(NULL)
{ };
};

thread_pool(long thread_num = 4);
~thread_pool();

void call(void (*fun)(void *), void *para = NULL)
{
assert(fun);
EnterCriticalSection(&_cs_work_queue);
_work_queue.push(new work_item(fun, para));
LeaveCriticalSection(&_cs_work_queue);
ReleaseSemaphore(_semaphore_call, 1, NULL);
}

void wait_end(long time_limit = INFINITE)//结束线程池, 并同步等待
{
SetEvent(_event_end);
WaitForSingleObject(_event_complete, time_limit);
}

void end()//结束线程池
{
SetEvent(_event_end);
}
};

thread_pool::thread_pool(long thread_num) : _thread_num(0), _runing_num(0)
{
InitializeCriticalSection(&_cs_work_queue);
InitializeCriticalSection(&_cs_threads);
_event_complete = CreateEvent(0, false, false, NULL);
_event_end = CreateEvent(0, true, false, NULL);
_semaphore_call = CreateSemaphore(0, 0, 0x7FFFFFFF, NULL);
assert(_semaphore_call && _event_complete && _event_end);
add(thread_num <= 0 ? 4 : thread_num);
}

thread_pool::~thread_pool()
{
DeleteCriticalSection(&_cs_work_queue);
DeleteCriticalSection(&_cs_threads);
CloseHandle(_event_end);
CloseHandle(_event_complete);
CloseHandle(_semaphore_call);
while(!_work_queue.empty())
{
delete _work_queue.front();
_work_queue.pop();
}
for(vector<thread_item*>::iterator iter=_threads.begin(); iter!=_threads.end(); iter++)
{
if(*iter)
{
CloseHandle((*iter)->_handle);
delete *iter;
}
}
}

DWORD WINAPI thread_pool::work_proc(LPVOID lpParameter)
{
thread_item * t_item = (thread_item*)lpParameter;
thread_pool *tp = t_item->_this;
HANDLE handle[2];
handle[0] = tp->_semaphore_call;
handle[1] = tp->_event_end;
InterlockedIncrement(&tp->_runing_num);

work_item * w_item = NULL;
bool do_proc;

for(;;)
{
DWORD wr = WaitForMultipleObjects(2, handle, false, INFINITE);
EnterCriticalSection(&tp->_cs_work_queue);
if(do_proc = !tp->_work_queue.empty())
{
w_item = tp->_work_queue.front();
tp->_work_queue.pop();
}
LeaveCriticalSection(&tp->_cs_work_queue);
if(wr == WAIT_OBJECT_0 + 1 && !do_proc)
break;
if(do_proc && w_item)
{
w_item->_fun(w_item->_para);
delete w_item;
}
}
InterlockedDecrement(&tp->_runing_num);
if(!tp->_runing_num)
SetEvent(tp->_event_complete);
return 0;
};
#endif
...全文
280 19 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
wujian53 2004-09-03
  • 打赏
  • 举报
回复
谢谢大家,结贴;
cjg325 2004-09-02
  • 打赏
  • 举报
回复
是这个函数调用 出错了
w_item->_fun(w_item->_para);
cjg325 2004-09-02
  • 打赏
  • 举报
回复
BOOL optval = TRUE;
if ( SOCKET_ERROR == setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (char *) &optval, sizeof( BOOL ) ) )
{
closesocket( s );
return false;
}
flashboy 2004-09-02
  • 打赏
  • 举报
回复
你这样的效率并不高,应该尽量避免线程互锁
wujian53 2004-09-01
  • 打赏
  • 举报
回复
我加了临界,同步不是问题
我该才有试了
void proc(void *para)
不会出错
正是怪了
虽然我一开始是的代码
DWORD WINAPI proc(void *para)

struct work_item
{
void (*_fun)(void *);//用户函数
void *_para; //用户参数
work_item(void (*fun)(void *) = NULL, void *para = NULL) : _fun(fun), _para(para)
{ };
};
中的void (*_fun)(void *);//用户函数
类型不一样
但也不至于改变了
EnterCriticalSection(&tp->_cs_work_queue);
if(do_proc = !tp->_work_queue.empty())
{
w_item = tp->_work_queue.front();
tp->_work_queue.pop();
}
LeaveCriticalSection(&tp->_cs_work_queue);
中的w_item = tp->_work_queue.front();返回值
我昨天有写了自己的对列也出现了同样的问题,自编的对列炉下
问题一样,但我发现在返回前对列你的数据是正确的
template<class T>
struct squeue_node
{
T _data;
squeue_node * _next;
squeue_node() : _next(NULL){};
squeue_node (T data) : _data(data), _next(NULL) {};
};

template<class T>
class squeue
{

squeue_node<T> * _begin;
squeue_node<T> * _end;
CRITICAL_SECTION _lock_cs;
unsigned int _size;
public:
squeue() : _begin(NULL), _end(NULL), _size(0)
{
InitializeCriticalSection(&_lock_cs);
}
~squeue()
{
clear();
DeleteCriticalSection(&_lock_cs);
}
void clear()
{
EnterCriticalSection(&_lock_cs);
for(squeue_node<T> * v = _begin, * t; v; )
{
t = v, v = v->_next;
delete t;
}
_begin = _end = NULL;
_size = 0;
LeaveCriticalSection(&_lock_cs);
}
bool empty()
{
EnterCriticalSection(&_lock_cs);
int s = _size;
LeaveCriticalSection(&_lock_cs);
return !s;
}
int size()
{
EnterCriticalSection(&_lock_cs);
int s = _size;
LeaveCriticalSection(&_lock_cs);
return s;
}
void push(const T &x)
{
EnterCriticalSection(&_lock_cs);
squeue_node<T> *ins = new squeue_node<T>(x);
assert(ins != NULL);
if(_end)
_end->_next = ins, _end = ins;
else
_begin = _end = ins;
_size ++;
LeaveCriticalSection(&_lock_cs);
}
T top()
{
EnterCriticalSection(&_lock_cs);
assert(_begin);
T x = _begin->_data;
LeaveCriticalSection(&_lock_cs);
return x;

}
T pop()
{
T x;
EnterCriticalSection(&_lock_cs);
if(_begin)
{
squeue_node<T> *t = _begin->_next;
x = _begin->_data;
delete _begin;
if(!t)
_begin = _end = NULL;
else
_begin = t;
_size --;
}
LeaveCriticalSection(&_lock_cs);
return x;
}
};

只是我不理解
DWORD /*WINAPI*/ proc(void *para)
的影响如此

要跳过了,还是去学重叠模型,完成端口
只是这段线程池的代码我用了许久,觉得简易,速度也不错
想不到也有BUG

Pandona 2004-09-01
  • 打赏
  • 举报
回复
mark,好东西
babam 2004-09-01
  • 打赏
  • 举报
回复
不知道是不是这个问题!
vc自己带的stl不是线程安全的
wujian53 2004-09-01
  • 打赏
  • 举报
回复
好像是可以了,为什么?
我只是发现了queue<work_item *> _work_queue 对列的数据弹出的出错
而且我曾经打印了对列的数据 是正确,只是在工作线程work_proc中除了问题
为何修改
DWORD /*WINAPI*/ proc(void *para)
就好了
好像不想干
我试过
void proc(void *para)
也会出错的
cjg325 2004-09-01
  • 打赏
  • 举报
回复
我觉得你的程序出错的时间可能会是随机的。

我估计是异步方面的问题,就好像一个还没有完,另外一个又开始了,我建议用I/OCP
可能好些。
wujian53 2004-09-01
  • 打赏
  • 举报
回复
在试了一次,不输出错误信息 12秒
丢失327个连接
wujian53 2004-09-01
  • 打赏
  • 举报
回复
我刚才由测试了一下
主客户端各100线程
开两万个连接
要25秒(同台机子p41.7 512M)

在服务器测试(2 各个至强2.4 ,2G)
要21秒
看来这种阻塞模型很菜
而且会丢失几十个连接
不知道为何
connect 抛出的错误是 10048 通常每个套接字地址 (协议/网络地址/端口) 只允许使用一次。
在本机就不会,也不知道为何
那位同志帮帮忙解决
我后天结贴
rockrabbit 2004-09-01
  • 打赏
  • 举报
回复
看看。
billcho 2004-09-01
  • 打赏
  • 举报
回复
有点意思。
crystal_heart 2004-09-01
  • 打赏
  • 举报
回复
up
videojet 2004-08-31
  • 打赏
  • 举报
回复
main.cpp(184):DWORD /*WINAPI*/ proc(void *para)
gdy119 2004-08-31
  • 打赏
  • 举报
回复
代码好长,看不懂!
wujian53 2004-08-31
  • 打赏
  • 举报
回复
我用命令编译(vc 6.0 p6)cl /MD /D "_X86_" $(FileName) /link ws2_32.lib oleaut32.lib user32.lib mswsock.lib
奇怪的是,这个线程池代码用了很久,都没问题;
最近学socket就出错了;
错误发生在 queue<work_item *> _work_queue; //工作队列
这个对列调用函数时
tp.call(time_proc, NULL);
加入函数指针及参数;
在工作线程中弹出;
发现弹出的指针不对,也不知为何;
帮帮忙;
我不会调试这样的代码,有STL and Thread and SOCKET;
wujian53 2004-08-31
  • 打赏
  • 举报
回复
//客户端 开10个线程接受接收到3个服务器端就出错
#pragma warning(disable: 4530)
#pragma warning(disable: 4786)

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
#include <ios>
#include <strstream>
using namespace std;
#include <winsock2.h>
#include <windows.h>
#include "thread_pool.h"

CRITICAL_SECTION cs;
long cc = 0;
void time_proc(void *para)
{
SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
if(s == INVALID_SOCKET)
{
EnterCriticalSection(&cs);
cout << __LINE__<<" socket error : " << WSAGetLastError() << endl;
LeaveCriticalSection(&cs);
}

struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(1001);
server.sin_addr.s_addr = inet_addr("192.18.17.89") ; EnterCriticalSection(&cs);
int ret = connect(s, (struct sockaddr*)&server, sizeof(server));
LeaveCriticalSection(&cs);
if(ret == SOCKET_ERROR)
{
EnterCriticalSection(&cs);
cout << __LINE__<<" connect error : " << WSAGetLastError() << endl;
LeaveCriticalSection(&cs);
return ;
}

char xx[200];
ret = recv(s, xx, 200, 0);
EnterCriticalSection(&cs);
if(ret == SOCKET_ERROR)
{
cout << __LINE__ << " recv error : " << WSAGetLastError() << endl;
LeaveCriticalSection(&cs);
closesocket(s);
return;
}
else
{
cout << "get " << ret << " char. " << endl << xx << endl;
LeaveCriticalSection(&cs);
}

ret = shutdown(s, SD_RECEIVE);
EnterCriticalSection(&cs);
if(ret == SOCKET_ERROR)
cout << __LINE__ << " shutdown error : " << WSAGetLastError() << endl;
LeaveCriticalSection(&cs);
closesocket(s);
InterlockedIncrement(&cc);
}

int main(int argc, char *argv[])
{
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2, 2);
WSAStartup(wVersionRequested, &wsaData);

InitializeCriticalSection(&cs);
long be = GetTickCount();
thread_pool tp(10);

for(int i=0; i<10; i++)
{
tp.call(time_proc, NULL);
}
tp.wait_end();

cout << GetTickCount() - be << endl;
DeleteCriticalSection(&cs);
cout << cc << endl;
WSACleanup();
return 0;
}
wujian53 2004-08-31
  • 打赏
  • 举报
回复
//服务器端
#pragma warning(disable: 4530)
#pragma warning(disable: 4786)
#include <map>
#include <cassert>
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
#include <exception>
#include <iomanip>
#include <ctime>
#include <queue>
#include <cstdio>
#include <list>
using namespace std;

#include <winsock2.h>
#include <windows.h>
#include <process.h>

CRITICAL_SECTION cs; //cout LOCK
long work_num = 0;

class thread_pool
{
protected:

static DWORD WINAPI work_proc(LPVOID lpParameter = NULL);//工作线程

struct work_item; //工作数据结构
struct thread_item; //线程数据结构
queue<work_item *> _work_queue; //工作队列
list<work_item *> _work_list; //工作队列
vector<thread_item *> _threads;//线程数据
CRITICAL_SECTION _cs_work_queue, _cs_threads; //工作队列临界, 线程数据临界
HANDLE _event_end, _event_complete, _semaphore_call;//结束事件, 完成事件, 工作信号
long _thread_num, _runing_num; //线程数, 运行的线程数

void add(int num)//添加线程
{
EnterCriticalSection(&_cs_threads);
for(int _i=0, i; _i<num; _i++)
{
i = _i + _thread_num;
_threads.push_back(new thread_item( this));
_threads[i]->_handle = CreateThread(NULL, 0, work_proc, _threads[i], 0, &(_threads[i]->_thread_id));
assert(_threads[i]->_handle);
}
_thread_num += num;
LeaveCriticalSection(&_cs_threads);
}

public:

struct work_item
{
void (*_fun)(void *);//用户函数
void *_para; //用户参数
work_item(void (*fun)(void *) = NULL, void *para = NULL) : _fun(fun), _para(para)
{ };
};

struct thread_item
{
unsigned long _thread_id; //线程ID
HANDLE _handle; //线程句柄
thread_pool* _this; //线程池的指针
thread_item(thread_pool *pthis) : _this(pthis), _handle(NULL)
{ };
};

thread_pool(long thread_num = 4);
~thread_pool();

void call(void (*fun)(void *), void *para = NULL)
{
assert(fun);
try
{
work_item *p;
EnterCriticalSection(&_cs_work_queue);
_work_queue.push(p = new work_item(fun, para));
LeaveCriticalSection(&_cs_work_queue);
EnterCriticalSection(&cs);
cout << " call() new work_item : "<< p << endl;
LeaveCriticalSection(&cs);
ReleaseSemaphore(_semaphore_call, 1, NULL);
}
catch(exception &e)
{
cout << e.what() << endl;
}
}

void wait_end(long time_limit = INFINITE)//结束线程池, 并同步等待
{
SetEvent(_event_end);
WaitForSingleObject(_event_complete, time_limit);
}

void end()//结束线程池
{
SetEvent(_event_end);
}
};

thread_pool::thread_pool(long thread_num) : _thread_num(0), _runing_num(0)
{
InitializeCriticalSection(&_cs_work_queue);
InitializeCriticalSection(&_cs_threads);
_event_complete = CreateEvent(0, false, false, "_event_complete_");
_event_end = CreateEvent(0, true, false, "_event_end_");
_semaphore_call = CreateSemaphore(0, 0, 0x7FFFFFFF, "_semaphore_call_");
assert(_semaphore_call && _event_complete && _event_end);
add(thread_num <= 0 ? 4 : thread_num);
}

thread_pool::~thread_pool()
{
DeleteCriticalSection(&_cs_work_queue);
DeleteCriticalSection(&_cs_threads);
CloseHandle(_event_end);
CloseHandle(_event_complete);
CloseHandle(_semaphore_call);
while(!_work_queue.empty())
{
delete _work_queue.front();
_work_queue.pop();
}
for(vector<thread_item*>::iterator iter=_threads.begin(); iter!=_threads.end(); iter++)
{
if(*iter)
{
CloseHandle((*iter)->_handle);
delete *iter;
}
}
}

DWORD WINAPI thread_pool::work_proc(LPVOID lpParameter)
{
thread_item * t_item = (thread_item*)lpParameter;
thread_pool *tp = t_item->_this;
HANDLE handle[2];
handle[0] = tp->_semaphore_call;
handle[1] = tp->_event_end;
InterlockedIncrement(&tp->_runing_num);

work_item * w_item = NULL;
bool do_proc;

for(;;)
{
DWORD wr = WaitForMultipleObjects(2, handle, false, INFINITE);
EnterCriticalSection(&tp->_cs_work_queue);
if(do_proc = !tp->_work_queue.empty())
{
w_item = tp->_work_queue.front();
//这里发生错误,原来加入函数队列的指针弹出时值变化
EnterCriticalSection(&cs);
cout <<" work_proc() w_item = tp->_work_queue.front() : "<< w_item << endl;
LeaveCriticalSection(&cs);

tp->_work_queue.pop();
}
LeaveCriticalSection(&tp->_cs_work_queue);
if(wr == WAIT_OBJECT_0 + 1 && !do_proc)
break;
if(do_proc && w_item)
{
w_item->_fun(w_item->_para);
delete w_item;
}
}
InterlockedDecrement(&tp->_runing_num);
if(!tp->_runing_num)
SetEvent(tp->_event_complete);
return 0;
};


DWORD WINAPI proc(void *para)
{
SOCKET s = *(SOCKET *)para;
delete para;
char xx[100];
sprintf(xx, "Server %d Send : %ld", s, GetTickCount());
Sleep(rand()%100) ;
int ret = send(s, xx, strlen(xx) + 1, 0);

EnterCriticalSection(&cs);
if(ret == SOCKET_ERROR)
{
cout << __LINE__ << " send error : " << WSAGetLastError() << endl;
closesocket(s);
LeaveCriticalSection(&cs);
return 0;
}
else
{
cout << s << " send " << ret << " char ( " << xx << " ) ."<< endl;
LeaveCriticalSection(&cs);
}

ret = shutdown(s, SD_SEND);

if(ret == SOCKET_ERROR)
{
EnterCriticalSection(&cs);
cout << __LINE__ << " shutdown error : " << WSAGetLastError() << endl;
LeaveCriticalSection(&cs);
closesocket(s);
return 0;
}
closesocket(s);
InterlockedDecrement(&work_num);
return 0;
}

int main(int argc, char *argv[])
{
try
{
WORD wVersionRequested;
WSADATA wsaData;
int len, ret;
wVersionRequested = MAKEWORD(2, 2);
ret = WSAStartup(wVersionRequested, &wsaData);

struct sockaddr_in server, client;

server.sin_family = AF_INET;
server.sin_port = htons(1001);
server.sin_addr.s_addr = inet_addr("192.18.17.89") ;

InitializeCriticalSection(&cs);
thread_pool tp(1);

SOCKET s, ns;
vector<SOCKET> vec_s;
vector<SOCKET>::iterator iter;
int i;

s = socket(AF_INET, SOCK_STREAM, 0);
if(s == INVALID_SOCKET)
cout << __LINE__<< " socket error : " << WSAGetLastError() << endl;

ret = bind(s, (struct sockaddr *)&server, sizeof(server));
if(ret == SOCKET_ERROR)
cout << __LINE__<< " bind error : " << WSAGetLastError() << endl;

ret = listen(s, 200);
if(ret == SOCKET_ERROR)
cout << __LINE__<< " listen error : " << WSAGetLastError() << endl;

for(i=0; i < 10; i++)
{
ns = accept(s, NULL, NULL);
if(ns != INVALID_SOCKET)
{
tp.call((void (*)(void *))proc, new SOCKET(ns));
}
else
{
EnterCriticalSection(&cs);
cout << __LINE__ << " accept error : " << WSAGetLastError() << endl;
LeaveCriticalSection(&cs);
}
}

tp.wait_end(); //等待线程结束
closesocket(s);
WSACleanup();
DeleteCriticalSection(&cs);
cout << work_num << endl;
}
catch(exception &e)
{
cout << e.what() << endl;
return 1;
}
return 0;
}

18,363

社区成员

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

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