linux下的c++ 多线程封装

来源:互联网 发布:钢材期货软件 编辑:程序博客网 时间:2024/06/16 06:07

最近为了学习linux 下的多线程,自己用c++封装了一个简易的局域网多线程聊天服务器,期间遇到了一些坑写到这里与大家共勉!
主要功能: 封装了一个名叫pthread_serv的类对每一个客户端的响应建立一个进程进行信息转发。
遇到的问题: 在使用linux提供的线程创建函数

int pthread_create(pthread_t *tidp,const pthread_attr_t *attr,(void*)(*start_rtn)(void*),void *arg) 

时因为线程主函数start_rt函数是pthread_serv类中的普通函数,在调用的时候c++ 会隐式的传入this指针,这样start_rtn就有了两个参数,但linux提供的pthread_create函数中start_rtn只能有一个(void*) 参数,这是个很严重的问题,我们编译都过不去…..
针对该问题的解决方法: 很明显,我们必须干掉start_rtn中这个可恶的this指针。现在有两个办法可以做到这点:
1. 将start_rtn声明为该类的友元函数
2. 将start_rtn声明为静态函数
我用了第二种方法,将start_rtn声明为静态函数,这样再调用

int pthread_create(pthread_t *tidp,const pthread_attr_t *attr,(void*)(*start_rtn)(void*),void *arg)

就没有问题了,不过旧问题去了,新问题又来了!!! 想哭…。c++ 中静态函数中只能调用静态成员,静态函数。所以start_rtn函数不能调用类里面的变量&&函数了,我也不能将所有的变量,函数都声明成静态的吧。所以我的解决方法是将this指针当做start_rtn的参数。

 pthread_create(&id_t,NULL,hander_clnt,this);

再在start_rtn中将参数类型转化成一个对象指针,用这个对象指针调用一个普通的函数,这个普通的函数就作为线程主函数使用。

void* pthread_serv::hander_clnt(void *msg) {     pthread_serv *serv = static_cast<pthread_serv*>(msg);     serv->run_clnt(); //run_clnt()就作为线程主函数用 }

下面是我的代码,比较搓,求轻拍..(逃~~)

#ifndef PTHREAD_SERV_H#define PTHREAD_SERV_H#include <iostream>#include <algorithm>#include <list>#include <string.h>#include <stdio.h>#include <arpa/inet.h> //sockaddr_in#include <pthread.h>#include <unistd.h>#include <sys/socket.h>class pthread_serv{public:    explicit pthread_serv();    inline void error_hander(char *msg);    static void *hander_clnt(void *msg);    void send_msg(char *msg,int len);    void run();    void run_clnt();    pthread_t id_t;private:    pthread_mutex_t mutex;    int serv_sock;    int clnt_sock;    sockaddr_in serv_addr;    sockaddr_in clnt_addr;    std::list<int> clnt_sock_list;};#endif // PTHREAD_SERV_H
#include "pthread_serv.h"pthread_serv::pthread_serv(){    serv_sock = socket(PF_INET,SOCK_STREAM,0);    memset(&serv_addr,0,sizeof(serv_addr));    serv_addr.sin_family = AF_INET;    serv_addr.sin_port = htons(8888);    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);    if(bind(serv_sock,(sockaddr*)&serv_addr,sizeof(serv_addr)) == -1)        error_hander("bind() error!");    if(listen(serv_sock,100) == -1)        error_hander("listen() error!");} inline void pthread_serv::error_hander(char *msg) {     fputs(msg,stdout); } void pthread_serv::send_msg(char *msg,int len) {     std::list<int>::iterator it;     pthread_mutex_lock(&mutex);   for(it=clnt_sock_list.begin(); it!=clnt_sock_list.end(); it++)         write(*it,msg,len);    pthread_mutex_unlock(&mutex); }void pthread_serv::run_clnt(){    int str_len;    char str[1000];    while ((str_len = read(clnt_sock,str,1000)) != 0)       send_msg(str,str_len);    pthread_mutex_lock(&mutex);    clnt_sock_list.remove(clnt_sock);    pthread_mutex_unlock(&mutex);    close(clnt_sock);} void* pthread_serv::hander_clnt(void *msg) {     pthread_serv *serv = static_cast<pthread_serv*>(msg);     serv->run_clnt(); }void pthread_serv::run(){    socklen_t clt_sz = sizeof(clnt_addr);    while (true)    {        clnt_sock = accept(serv_sock,(sockaddr*)&clnt_addr,&clt_sz);        fprintf(stdout,"new connect: %s\n",inet_ntoa(clnt_addr.sin_addr));        pthread_create(&id_t,NULL,hander_clnt,this);        pthread_detach(id_t);        pthread_mutex_lock(&mutex);        clnt_sock_list.push_back(clnt_sock);        pthread_mutex_unlock(&mutex);    }}
0 0