目录(?)[-]
- 一基本原理
- 二对Socket的封装
- 三线程池的实现
- 四连接池的实现
- 五监听线程的实现
一、基本原理
有时候我们需要实现一个公共的模块,需要对多个其他的模块提供服务,最常用的方式就是实现一个Socket Server,接受客户的请求,并返回给客户结果。
这经常涉及到如果管理多个连接及如何多线程的提供服务的问题,常用的方式就是连接池和线程池,基本流程如下:
首先服务器端有一个监听线程,不断监听来自客户端的连接。
当一个客户端连接到监听线程后,便建立了一个新的连接。
监听线程将新建立的连接放入连接池进行管理,然后继续监听新来的连接。
线程池中有多个服务线程,每个线程都监听一个任务队列,一个建立的连接对应一个服务任务,当服务线程发现有新的任务的时候,便用此连接向客户端提供服务。
一个Socket Server所能够提供的连接数可配置,如果超过配置的个数则拒绝新的连接。
当服务线程完成服务的时候,客户端关闭连接,服务线程关闭连接,空闲并等待处理新的任务。
连接池的监控线程清除其中关闭的连接对象,从而可以建立新的连接。
二、对Socket的封装
Socket的调用主要包含以下的步骤:
调用比较复杂,我们首先区分两类Socket,一类是Listening Socket,一类是Connected Socket.
Listening Socket由MySocketServer负责,一旦accept,则生成一个Connected Socket,又MySocket负责。
MySocket主要实现的方法如下:
int MySocket::write(const> int left = length; |
int MySocket::read(char *> int left = length; return index; |
int MySocket::status() > if(status < 0) |
int MySocket::close() |
int MySocketServer::init(int> { > { > lin.l_linger = 0; > m_inited = true; |
MySocket * MySocketServer::accept() |
MySocket * MySocketServer::accept(int> timeout.tv_usec = 0; > if(status < 0) if(FD_ISSET(m_socket, &checkset)) |
三、线程池的实现
一个线程池一般有一个任务队列,启动的各个线程从任务队列中竞争任务,得到的线程则进行处理:list<MyTask *> >
void * __thread_new_proc(void *p)
{
((MyThread *)p)->run();
>
int MyThread::start()
{
> pthread_attr_destroy(&attr);
> return –1;
}
int MyThread::stop()
{
>
> return –1;
}
int MyThread::join()
{
>
>
return –1;
}
void MyThread::run()
{
>
{
MyTask *pTask =>
{
>
int MyThreadPool::init()
{
> pthread_condattr_destroy(&cond_attr);
> return –1;
> pthread_mutexattr_destroy(&attr);
> return –1;
> {
MyThread *thread = new MyThread(i+1, this);
m_threads.push_back(thread);
}
return 0;
}
int MyThreadPool::start()
{
int ret;
> {
> if (ret != 0)
>
> return –1;
return 0;
}
void MyThreadPool::addTask(MyTask *ptask)
{
> return;
pthread_mutex_lock(&m_queueMutex);
m_taskQueue.push_back(ptask);
if (m_waitingThreadCount > 0)
pthread_cond_signal(&m_cond);
pthread_mutex_unlock(&m_queueMutex);
}
MyTask * MyThreadPool::getNextTask()
{
MyTask *pTask = NULL;
> {
++m_waitingThreadCount;
>
>
void MyTask::process()
{
//用read从客户端读取指令
//对指令进行处理
//用write向客户端写入结果
}
四、连接池的实现
每个连接池保存一个链表保存已经建立的连接:list<MyConnection *> *>
void MyConnectionPool::addConnection(MyConnection *>
void MyConnectionPool::managePool()
{
> {
MyConnection *conn = *itr;
> list<MyConnection *>::iterator pos = itr++;
m_connections->erase(pos);
}
else if (conn->isError())
{
//处理错误的连接
++itr;
}
else
{
++itr;
}
}
pthread_mutex_unlock(&m_connectionMutex);
}
五、监听线程的实现
监听线程需要有一个MySocketServer来监听客户端的连接,每当形成一个新的连接,查看是否超过设置的最大连接数,如果超过则关闭连接,如果未超过设置的最大连接数,则形成一个新的MyConnection,将其加入连接池和线程池。
MySocketServer *pServer => while (!stopFlag) { MySocket *> > { > > 更多0
|