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
- linux下的c++ 多线程封装
- Linux下的C多线程编程
- Linux下的C多线程编程
- Linux下的C多线程编程
- Linux下的C语言多线程编程
- Linux下的C语言多线程编程
- Linux下C语言的多线程编程
- linux下c语言的多线程编程
- Linux下c实现域名转IP的方法封装
- linux下C语言多线程
- linux下C语言多线程
- Linux下C语言多线程
- Linux下C多线程编程
- Linux下C多线程编程
- Linux 下 c 多线程学习
- linux下C实现多线程
- linux下的多线程
- linux下的多线程
- SVN安装步骤
- 图像金字塔
- 自学iOS开发系列----UI(常用控件:UIAlertController、UIPickerView、UIProgressView、UIWebView、UISwitch)
- 《转》单例模式中的懒汉模式和恶汉模式的区别
- 用ionic快速开发hybird App(已附源码,在下面+总结见解)
- linux下的c++ 多线程封装
- Vue.js中的列表渲染:v-for
- ubuntu server提示ImportError: No module named Tkinter错误
- ListView + SpringView,实现条目的数据展示
- leetcode_136 Single Number-找数组中唯一的单身数
- DateScroller自定义控件横向滑动日历选择器
- 虚机迁移流程
- AIDL解析(二 )让Service主动调起Activity吧!
- 练习项目备选清单