windows socket端口监听和多线程任务处理

来源:互联网 发布:智能网络电视哪个好 编辑:程序博客网 时间:2024/06/06 20:38

本文本应该是和上一篇在一起的一个程序,但是由于是不同的内容,所以分开来写了。

整体思路是将端口监听程序写成一个服务,然后如果遇到服务请求就创建一个新的线程来处理这个请求,在原线程中用一个数组来记录当前所有的请求。本程序在VS2010下测试通过。下面是监听程序,使用非阻塞式socket,使用select来检查是否有请求到来。

DWORD CSampleService::ListenThread(void){// Periodically check if the service is stopping.u_long iMode = 1;ioctlsocket(listenSocket,FIONBIO,&iMode);struct sockaddr_in tmp_addr;memset(&tmp_addr,0,sizeof(tmp_addr));int addrlen = sizeof(tmp_addr);//ioctlsocket(clientSocket,FIONBIO,&iMode);SOCKET tmp_socket;fd_set fdread;   int ret;   struct timeval tv = {1, 0};   while(!m_fStopping){FD_ZERO(&fdread);     FD_SET(listenSocket, &fdread); ret = select(0, &fdread, NULL, NULL, &tv); if (ret==0) continue;if((tmp_socket=accept(listenSocket,(sockaddr*)&tmp_addr,&addrlen))!=INVALID_SOCKET){HANDLE htmp2_s;BOOL bSuccess = DuplicateHandle(GetCurrentProcess(),(HANDLE)tmp_socket,GetCurrentProcess(),&htmp2_s,STANDARD_RIGHTS_REQUIRED,TRUE,DUPLICATE_SAME_ACCESS); this->active_address_list.push_back(tmp_addr);this->active_socket_list.push_back((SOCKET)(htmp2_s));int curr_threadID=active_socket_list.size()-1;comm_thread *ct1=new comm_thread(this,curr_threadID);CThreadPool::QueueUserWorkItem(&(comm_thread::run_comm_thread),ct1);ReleaseMutex(conn_num_mutex);WaitForSingleObject(conn_num_mutex, INFINITE); this->active_comm_list.push_back(ct1);++connection_num;log_stream<<"INFO: Accept connection from "<<inet_ntoa(tmp_addr.sin_addr)<<". Connection number: "<<connection_num<<std::endl;ReleaseMutex(conn_num_mutex);}//log_stream<<"INFO: Not blocked"<<std::endl;}ReleaseMutex(conn_num_mutex);log_stream<<"INFO: listenThread is stopping"<<std::endl;WaitForSingleObject(conn_num_mutex, INFINITE); --connection_num;if (connection_num==0) SetEvent(m_hStoppedEvent);ReleaseMutex(conn_num_mutex);return 0;}


在监听线程创建的任务处理线程中执行以下函数,这里只是简单的将客户端发来的数据发送回去。

DWORD comm_thread::run_comm_thread(){char buf[4096];int bytes;fd_set fdread;int ret;   struct timeval tv = {1, 0};while (!listen_thread->m_fStopping){// Perform main service function here...//::Sleep(2000);  // Simulate some lengthy operations.FD_ZERO(&fdread);     FD_SET(clientSocket, &fdread); ret = select(0, &fdread, NULL, NULL, &tv); if (ret==0) continue;if((bytes=recv(clientSocket,buf,sizeof(buf),0))!=SOCKET_ERROR){buf[bytes]='\0';(listen_thread->log_stream)<<"INFO: Message from "<<inet_ntoa(clientAddress.sin_addr)<<"through threadID "<<this->threadID<<":"<<buf<<std::endl;if (bytes==1&&buf[0]=='q') break;if(send(clientSocket,buf,bytes,0)==SOCKET_ERROR){(listen_thread->log_stream)<<"ERR: 发送数据失败"<<std::endl;}}//log_stream<<"INFO: Not blocked"<<std::endl;}(listen_thread->log_stream)<<"INFO: conn="<<listen_thread->connection_num<<" threadID "<<threadID<<std::endl;char bye[]="  Service is stopping";*bye='0'+this->threadID;send(clientSocket,bye,strlen(bye),0);// Signal the stopped event.WaitForSingleObject(listen_thread->conn_num_mutex, INFINITE); --listen_thread->connection_num;listen_thread->active_comm_list.pop_back();if (listen_thread->connection_num==0) SetEvent(listen_thread->m_hStoppedEvent);ReleaseMutex(listen_thread->conn_num_mutex);this->~comm_thread();return 0;}


其中有一部分代码参考的网上的代码,之后打算将这个代码进一步写成一个中文分词服务程序。初次写socket通信以及windows服务程序,各位看官如果有建议,请不吝赐教。