linux下的c++ 多线程封装

本文介绍了一个基于C++实现的简易局域网多线程聊天服务器。通过封装pthread_serv类来处理客户端连接,并解决了因C++中this指针导致的线程创建问题。文中详细记录了解决过程及代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近为了学习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);

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值