本文本应该是和上一篇在一起的一个程序,但是由于是不同的内容,所以分开来写了。
整体思路是将端口监听程序写成一个服务,然后如果遇到服务请求就创建一个新的线程来处理这个请求,在原线程中用一个数组来记录当前所有的请求。本程序在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服务程序,各位看官如果有建议,请不吝赐教。