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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值