DWORD WINAPI WorkItem(LPVOID lpParameter) ;
/*有加WINAPI的函数基本可以说明系统将在某个时候会自己调用着个函数
WINAPI 即 __stdcall ,他是函数调用约定的一种,函数调用约定主要约束了两件事
1.参数传递顺序,2.调用堆栈由谁(调用函数或被调用函数)清理
__stdcall表示 1.参数从右向左压入堆栈, 2.函数被调用者修改堆栈
*/
int main()
{
// cin>>FLAG;
//线程池开辟
CompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
// BeginTime = GetTickCount();
//连接创建阶段
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
printf("WSAStartup failed !\n");
// return -1;
}
//创建监听套接字
SOCKET sockfd;
if ( (sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) ) == INVALID_SOCKET)
{
printf("socket failed !\n");
WSACleanup();
// return -1;
}
//设置服务器地址
struct sockaddr_in servaddr;
memset(&servaddr, 0,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(9999);
servaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
//绑定socket地址结构到监听套接字
if (bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0) {
printf("bind failed !\n");
closesocket(sockfd);
WSACleanup();
}
//在Server上进行监听
if (listen(sockfd, 4) != 0) {
printf("listen failed !\n");
closesocket(sockfd);
WSACleanup();
// return -1;
// break;
}
//接受客户端的连接请求
printf("TCP Server Start...\n");
HINSTANCE hInst=LoadLibrary("Kernel32.DLL"); //载入指定的动态链接库,并将它映射到当前进程使用的地址空间。
//一旦载入,即可访问库内保存的资源,成功则返回库模块的句柄,零表示失败。会设置GetLastError
if(hInst)
{
typedef BOOL(WINAPI * MYFUNC)(LPTHREAD_START_ROUTINE, PVOID,ULONG);
//声明MYFUNC函数类型
MYFUNC MyQueueUserWorkItem=NULL;
//取得QueueUserWorkItem函数指针
MyQueueUserWorkItem=(MYFUNC)GetProcAddress(hInst,"QueueUserWorkItem");
//(DLL句柄,函数名)检索指定的动态链接库(DLL)中的输出库函数地址
//queueuserworkitem,将方法排入队列以便执行,并指定包含该方法所用数据的对象。此方法在有线程池线程变得可用时执行。
//加载DLL,将MYFUNC指向DLL中的QueueUserWorkItem函数
if(!MyQueueUserWorkItem)
{
MessageBox(NULL,"获取函数地址失败","你好!",MB_OK);
return 0;
}
struct sockaddr_in cliaddr1;
int cliaddrlen = sizeof(cliaddr1); //cliaddrlen需要有初值,作为一个值-结果参数参与函数
memset(&cliaddr1,0, sizeof(cliaddr1)); //memset(&cliaddr, 0, sizeof(cliaddr));
SOCKET connfd;
int flag_thread = 0;
// lp_perhandle perhandledata;
LP_PERHANDLE prehandledata;
//循环等待
while (1)
{
connfd = accept(sockfd, (struct sockaddr *)&cliaddr1, &cliaddrlen);
perhandledata = new PERHANDLE();
ZeroMemory(perhandledata, sizeof(PERHANDLE));
perhandledata->connected=connfd;
perhandledata->cliaddr=cliaddr;
// connected=connfd;
perhandledata->flag=++flag_thread;
MyQueueUserWorkItem(WorkItem, (LPVOID)&perhandledata, 0x00000010);
int a = flag_thread;
//WT_EXECUTELONGFUNCTION,如果线程池中线程都处于忙状态,WINDOWS将自动创建新的线程
}
}
// SetEvent(CompleteEvent);
FreeLibrary(hInst);
WaitForSingleObject(CompleteEvent, INFINITE);
CloseHandle(CompleteEvent);
return 0;
}
DWORD WINAPI WorkItem(LPVOID lpParameter)
{
lp_perhandle perhandle_thread=(lp_perhandle)&lpParameter;
SOCKET connfd=perhandle_thread->connected;
sockaddr_in client_thread=perhandle_thread->cliaddr1;
int flag=perhandle_thread->flag;
// int flag = (int)lpParameter;
// SOCKET connfd=connected;
char buff[100];
extern sockaddr_in cliaddr;
// flag_thread++;
extern int FLAG;
int ret;
// cout<<flag<<endl;
// flag1=flag_thread;
// cout<<flag1;
// cout<<FLAG;
while (true)
{
// send(connfd, "stop", sizeof(buff), 0);
ret = recv(connfd, buff, sizeof(buff), 0);
if (ret == SOCKET_ERROR)
{
/*
printf("recv failed !\n");
closesocket(connfd);
WSACleanup();
return -1;
*/
break;
}
//为了避免打印错误,将字符串buff结尾设成0x00
buff[ret] = 0x00;
//获取当前系统时间
SYSTEMTIME st;
GetLocalTime(&st);
char SysDate[30];
sprintf(SysDate, "%4d-%2d-%2d %2d:%2d:%2d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
printf("%s Recv from Client [%s:%d] : %s\n", SysDate, inet_ntoa(client_thread.sin_addr), ntohs(client_thread.sin_port), buff);
}
//释放资源
closesocket(connfd);
return 0;
}
大体是这样,最近在修改参数传输的问题,计划将套接字,地址,线程ID设计为一个数据结构,传入工作线程中