windows线程池



// serverDlg.cpp : 实现文件
//


#include "stdafx.h"
#include "server.h"
#include "serverDlg.h"
#include "afxdialogex.h"
#include "winsock2.h"
#include<Windows.h>
#include<iostream>
#include<cstdlib>




#ifdef _DEBUG
#define new DEBUG_NEW
#endif




// 用于应用程序“关于”菜单项的 CAboutDlg 对话框


class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();


// 对话框数据
enum { IDD = IDD_ABOUTBOX };


protected:
virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持


// 实现
protected:
DECLARE_MESSAGE_MAP()
};


CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}


void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()




// CserverDlg 对话框


CserverDlg::CserverDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CserverDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}


void CserverDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(CserverDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
END_MESSAGE_MAP()








extern int create_listen_thread(unsigned int listen_port);


// CserverDlg 消息处理程序
BOOL CserverDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();


// 将“关于...”菜单项添加到系统菜单中。


// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);


CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}


// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
//  执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标


// TODO: 在此添加额外的初始化代码


create_listen_thread(8008);


return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}


void CserverDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}


// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。
void CserverDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文


SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);


// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;


// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}


//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CserverDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}


typedef struct 
{
SOCKET socket_connected;
struct sockaddr_in addr_client;
}STRUCT_CLIENT_MSG;


SOCKET SOCKET_LISTEN;
HANDLE HANDLE_SERVER_LISTEN_THREAD;//服务器线程句柄


//VOID CALLBACK WorkCallback(PTP_CALLBACK_INSTANCE Instance,PVOID Context,PTP_WORK Work)
//{
//    //cout<<"this is WorkCallback function!"<<endl;
//}


//DWORD WINAPI ThreadProcessClient(void* lpParam)
VOID CALLBACK WorkCallback(PTP_CALLBACK_INSTANCE Instance,PVOID lpParam,PTP_WORK Work)
{
STRUCT_CLIENT_MSG *p_clt_msg = (STRUCT_CLIENT_MSG *)lpParam;
timeval tv_socket;
fd_set fd_socket;
DWORD ret=0;
int rev_num=0;
unsigned int fd_read_num=0;
unsigned int i;
unsigned char *recv_buf;
unsigned char result=0;
unsigned char send_buff[32]="12345fdfjidjfkd";


MessageBox(NULL,"A client connected!","Server",1);


while(1)
{
//分配一块内存来存储接收数据
recv_buf = (unsigned char *)HeapAlloc(GetProcessHeap(),0,128);
if(recv_buf==NULL)
{
closesocket(p_clt_msg->socket_connected);
HeapFree(GetProcessHeap(),0,p_clt_msg);
ret = -1;
continue;//return ;
}

//清空集合,并将socket事件放到等待集合里
FD_ZERO(&fd_socket);
FD_SET(p_clt_msg->socket_connected,&fd_socket);

//设置等待时间,调节这个值,可调整通信超时时间
tv_socket.tv_sec  = 5;
tv_socket.tv_usec = 0;//80000;

//等待事件完成
fd_read_num = select(2,&fd_socket,NULL,NULL,&tv_socket);
if(fd_read_num>0)//事件完成
{
rev_num = recv(p_clt_msg->socket_connected,(char *)recv_buf, 128, 0);
FD_CLR(p_clt_msg->socket_connected, &fd_socket);
if(rev_num<=0)
{
closesocket(p_clt_msg->socket_connected);
//HeapFree(GetProcessHeap(),0,recv_buf);
//HeapFree(GetProcessHeap(),0,p_clt_msg);
ret = -2;
continue;//return ;
}
}
else//超时后事件仍未完成
{
FD_CLR(p_clt_msg->socket_connected,&fd_socket);
closesocket(p_clt_msg->socket_connected);
HeapFree(GetProcessHeap(),0,recv_buf);
HeapFree(GetProcessHeap(),0,p_clt_msg);
ret = -3;
continue;//return ;
}


send(p_clt_msg->socket_connected,(char *)send_buff,10,0);


//关闭连接客户端的socket
//closesocket(p_clt_msg->socket_connected);

//内存用完后,要释放掉
HeapFree(GetProcessHeap(),0,p_clt_msg);
HeapFree(GetProcessHeap(),0,recv_buf);


Sleep(10);


}
return ;
}




DWORD WINAPI server_listen_thread(void* lpParam)
{
SOCKET *socket_accept = (SOCKET *)lpParam;
SOCKET connect_socket;
struct sockaddr_in addr_client;
int addr_in_len = sizeof(addr_client);

STRUCT_CLIENT_MSG *p_clt_msg;
HANDLE handle_rev_data_thread = NULL;

PTP_WORK tpWork;


//创建工作对象
    //tpWork = CreateThreadpoolWork(WorkCallback,p_clt_msg,NULL);
PTP_POOL ptp_server;


/* 创建定制线程池 */
ptp_server = CreateThreadpool(NULL);

//CloseThreadpool(ptp_server);


/* 设置线程池的最小和最大线程数量 */
SetThreadpoolThreadMinimum(ptp_server,1);
SetThreadpoolThreadMaximum(ptp_server,2);


// 初始化“回调函数环境”结构
TP_CALLBACK_ENVIRON tcbe;
InitializeThreadpoolEnvironment(&tcbe);


// 将该回调函数环境结构与线程池相关联
SetThreadpoolCallbackPool(&tcbe, ptp_server);


// 创建清理组
PTP_CLEANUP_GROUP pTpcg= CreateThreadpoolCleanupGroup();
// 将回调函数环境结构与清理组关联起来
SetThreadpoolCallbackCleanupGroup(&tcbe, pTpcg, NULL);


现在可以创建一些项,提交给线程池
//PTP_WORK pTpWork = CreateThreadpoolWork(, &tcbe);// 创建一个工作项
//SubmitThreadpoolWork(pTpWork);    // 提交工作项


while(1)
{
//等待客户端连接
connect_socket = accept(*socket_accept,(struct sockaddr *)&addr_client,&addr_in_len);
if(connect_socket==INVALID_SOCKET)
{
continue;
}


//MessageBox(NULL,"A client connected!","Server",1);


//有客户端连接到服务器,则立即分配一块内存来存储客户端socket信息
p_clt_msg = (STRUCT_CLIENT_MSG *)HeapAlloc(GetProcessHeap(),0,sizeof(STRUCT_CLIENT_MSG));
if(p_clt_msg == NULL)
{
closesocket(connect_socket);
continue;
}


//拷贝客户端socket信息到分配的内存块
p_clt_msg->socket_connected = connect_socket;
p_clt_msg->addr_client.sin_addr.S_un.S_un_b.s_b1 = addr_client.sin_addr.S_un.S_un_b.s_b1;
p_clt_msg->addr_client.sin_addr.S_un.S_un_b.s_b2 = addr_client.sin_addr.S_un.S_un_b.s_b2;
p_clt_msg->addr_client.sin_addr.S_un.S_un_b.s_b3 = addr_client.sin_addr.S_un.S_un_b.s_b3;
p_clt_msg->addr_client.sin_addr.S_un.S_un_b.s_b4 = addr_client.sin_addr.S_un.S_un_b.s_b4;
p_clt_msg->addr_client.sin_family = addr_client.sin_family;
p_clt_msg->addr_client.sin_port = addr_client.sin_port;




// 现在可以创建一些项,提交给线程池
PTP_WORK pTpWork = CreateThreadpoolWork(WorkCallback,p_clt_msg,&tcbe);// 创建一个工作项
SubmitThreadpoolWork(pTpWork);    // 提交工作项


创建一个新的线程来处理该客户端连接
//handle_rev_data_thread = CreateThread(NULL,0,ThreadProcessClient,(void *)p_clt_msg,0,NULL);
//if(handle_rev_data_thread == NULL)
//{
// closesocket(connect_socket);
// HeapFree(GetProcessHeap(),0,p_clt_msg);
// continue;
//}


}


return 0;
}


int create_listen_thread(unsigned int listen_port)
{
WSADATA wsadata;
char *host_ip = NULL;
unsigned char host_ip_len = 0;
unsigned char i=0;
int result;


char pc_name[64];
PHOSTENT hostinfo;

SOCKET socket_ser_listen;
SOCKADDR_IN addr_in_ser;






//初始化Winsock服务,这里我们使用2.2版本的socket
result = WSAStartup(MAKEWORD(2,2),&wsadata);
if( NO_ERROR != result )
{
return -1;
}


//获取本机IP地址
if( gethostname(pc_name,sizeof(pc_name))==NO_ERROR )//获取主机名称
{
if( (hostinfo=gethostbyname(pc_name))!=NULL )//获取主机信息
{
host_ip = inet_ntoa(*(struct in_addr *)*hostinfo->h_addr_list);//获取本机IP
}
else
{
WSACleanup();
return -2;
}
}
else
{
WSACleanup();
return -3;
}




//申请一个socket做服务器
socket_ser_listen = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(INVALID_SOCKET==socket_ser_listen)
{
return -4;
}


//将本机的8008端口绑定到上面申请的服务器socket
addr_in_ser.sin_family = AF_INET;
addr_in_ser.sin_addr.s_addr =inet_addr(host_ip);
addr_in_ser.sin_port = htons(listen_port);
result = bind(socket_ser_listen, (struct sockaddr *)&addr_in_ser, sizeof(addr_in_ser));
if(SOCKET_ERROR==result)
{
return -5;
}
//将服务器socket置于监听状态
result = listen(socket_ser_listen,SOMAXCONN);
if(SOCKET_ERROR==result)
{
return -6;
}




//创建服务器监听线程
SOCKET_LISTEN = socket_ser_listen;//将服务器socket放到全局变量里传给服务器线程,不能用
HANDLE_SERVER_LISTEN_THREAD = CreateThread(NULL,0,server_listen_thread,(void *)&SOCKET_LISTEN,0,NULL);
if( NULL==HANDLE_SERVER_LISTEN_THREAD )
{
return -7;
}

return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值