解决linux底下cmake编译使用C++ 11标准库自带的thread报错问题

本人在编写linux底下socket编程测试服务端时候,发现使用std::thread函数时候,cmake编译通过,make编译失败 ,CMakeLists.txt如下:

cmake_minimum_required(VERSION 3.10)
project(Server)


set(SERVER_INC ./include)
message(STATUS,"SERVER_INC is ${SERVER_INC}")
include_directories(${SERVER_INC})
file(GLOB H_FILE ${SERVER_INC}/*.h)
message(STATUS,"H_FILE is ${H_FILE}")
set(SOURCE 
                main.cpp
                Server.cpp
                ${H_FILE})
message(STATUS,"SOURCE is ${SOURCE}")
add_executable(${PROJECT_NAME} ${SOURCE})  

Server.cpp如下

Server::Server(/* args */)
{
     Server::m_last_closed=-1;
     Server::m_isonline=false;
     
}

Server::~Server()
{
    for(int i=0;i<newSocket.size();i++)
    {
        detach(i);
    }
    closed();
}
void  Server::AcceptTask(descript_socket argv)
{
    try
    {
        /* code */

        int n=-2;
        struct descript_socket desc = (struct descript_socket) argv;
        
        std::  cerr << "服务端open client[ id:"<< desc.id <<" ip:"<< desc.ip <<" socket:"<< desc.socketfd<<" send:"<< desc.enable_message_runtime <<" ]" << std::endl;
        while(1)
        {
            n = recv(desc.socketfd, msg, MAXPACKETSIZE, 0);
            if(n != -1) 
            {
                if(n==0)
                {
                    Server::m_isonline=true;
                    
                    std::cerr << "服务端close client[ id:"<< desc.id <<" ip:"<< desc.ip <<" socket:"<< desc.socketfd<<" ]" << std::endl;
                    Server::m_last_closed = desc.id;
                    close(desc.socketfd);

                    int id = desc.id;
                    auto new_end = std::remove_if(newSocket.begin(), newSocket.end(),
                                                        [id](descript_socket device)
                                                            { return device.id == id; });
                    newSocket.erase(new_end, newSocket.end());

                    if(m_clientNum>0) 
                    {
                        m_clientNum--;
                    }
                    break;
                }
                msg[n]=0;
                desc.message = std::string(msg);
                std::lock_guard<std::mutex> guard(m_mutex);
                Message.emplace_back( desc );
            }
            usleep(600);
        }
     
        std::cerr << "exit thread: " << std::this_thread::get_id() << std::endl;
       

        

    }
    catch(const std::exception& e)
    {
        std::cerr << e.what() << '\n';
       
    }
    
   
}

bool Server::SetUp(std::string ip,int port,int protocolType)
{
    try
    {
        
            /* code */
            //1.创建一个socket
        int m_sockfd=socket(AF_INET,(IPPROTO_TCP == protocolType)? SOCK_STREAM : SOCK_DGRAM,protocolType);

        if(m_sockfd<0)
        {
            std::cerr<<"服务端socket create fail"<<std::endl;
            return false;
        }
        else
        {
            std::cerr<<"服务端socket创建"<<std::endl;
        }
        //2.准备通讯地址(必须是服务器的)的IP
        memset(&m_serverAddress,0,sizeof(m_serverAddress));
        m_serverAddress.sin_family = AF_INET;
        m_serverAddress.sin_port = htons(port);//将一个无符号短整型的主机数值转换为网络字节顺序,即大尾顺序(big-endian)
        m_serverAddress.sin_addr.s_addr = inet_addr(ip.c_str());//net_addr方法可以转化字符串,主要用来将一个十进制的数转化为二进制的数,用途多于ipv4的IP转化。
        //3.bind()绑定
        //参数一:0的返回值(socket_fd)
        //参数二:(struct sockaddr*)&addr 前面结构体,即地址
        //参数三: addr结构体的长度
        int bind_fd=bind(m_sockfd,(struct sockaddr*)&m_serverAddress,sizeof(m_serverAddress));
        if(bind_fd<0)
        {
            std::cerr<<"服务端bind绑定失败"<<std::endl;
            return false;
        }
        else
        {
            
            std::cerr<<"服务端bind绑定成功"<<std::endl;
        }
        
        //4.监听客户端listen()函数
    //参数二:进程上限,一般小于30
        int listen_fd=listen(m_sockfd,30);
        if(listen_fd<0)
        {
            std::cerr<<"服务端listen error"<<std::endl;
            return false;
        }
        m_isonline=true;
        m_clientNum=0;
        return true;
    }
    catch(const std::exception& e)
    {
        std::cerr << e.what() << '\n';
        return false;
    }
    
   
}

bool Server::Accepted()
{
    try
    {
        //5.等待客户端的连接accept(),返回用于交互的socket描述符
        /* code */
        memset(&m_clientAddress,0,sizeof(m_clientAddress));
        socklen_t clientAddressLength=sizeof(m_clientAddress);
        descript_socket des_socket;
        des_socket.socketfd=accept(m_sockfd,(struct sockaddr*)&m_clientAddress,&clientAddressLength);
        des_socket.id=m_clientNum;
        des_socket.ip=inet_ntoa(m_clientAddress.sin_addr);
        newSocket.emplace_back(des_socket);
        std::cerr << "服务端accept client[ id:" << newSocket[m_clientNum].id<< 
                        " ip:" << newSocket[m_clientNum].ip << 
                    " handle:" << newSocket[m_clientNum].socketfd << " ]" << std::endl;
        if(newSocket[m_clientNum].socketfd<0)
        {
            std::cerr<<"服务端newSocket"<<"clientNum="<<m_clientNum<<"accept失败"<<std::endl;
        }
         std::thread t(&Server::AcceptTask,this,newSocket[m_clientNum]);
      
       
        
        m_isonline=true;
        m_clientNum++;
        return true;

    }
    catch(const std::exception& e)
    {
        std::cerr << e.what() << '\n';
        return false;
    }
    
    
}
std::vector<descript_socket> Server::getMessage()
{  
 
        /* code */
          std::lock_guard<std::mutex> guard(m_mutex);
            return Message; 

    


}
bool Server::Send(std::string msg,int id)
{
    try
    {
        /* code */
         int Sendfd=send(newSocket[id].socketfd,msg.c_str(),sizeof(msg),0);
            if(Sendfd<0)
            {
                std::cerr<<"服务端Sendfd<0,send失败"<<std::endl;
                return false;
            }
            return true;
    }
    catch(const std::exception& e)
    {
        std::cerr << e.what() << '\n';
        return false;
    }
    
  
}
std::string Server::get_ip_addr(int id)
{
	return newSocket[id].ip;
}

bool Server::is_online() 
{
	return m_isonline;
}

void Server::detach(int id)
{
	close(newSocket[id].socketfd);
	newSocket[id].ip = "";
	newSocket[id].id = -1;
	newSocket[id].message = "";
} 

void Server::closed() 
{
   close(m_sockfd);
}
int Server::get_last_closed_sockets()
{
	return Server::m_last_closed;
}
void Server::clean(int id)
{
	
	memset(msg, 0, MAXPACKETSIZE);
}

运行cmake .

lx@lx-virtual-machine:~/my-codes/C++/Others/Socket/Server$ cmake .
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
STATUS,"SERVER_INC is ./include"
STATUS,"H_FILE is /home/lx/my-codes/C++/Others/Socket/Server/./include/Server.h"
STATUS,"SOURCE is main.cppServer.cpp/home/lx/my-codes/C++/Others/Socket/Server/./include/Server.h"
-- Configuring done
-- Generating done
-- Build files have been written to: /home/lx/my-codes/C++/Others/Socket/Server

运行make 后报错

lx@lx-virtual-machine:~/my-codes/C++/Others/Socket/Server$ make 
Scanning dependencies of target Server
[ 33%] Building CXX object CMakeFiles/Server.dir/main.cpp.o
[ 66%] Building CXX object CMakeFiles/Server.dir/Server.cpp.o
[100%] Linking CXX executable Server
/usr/bin/ld: CMakeFiles/Server.dir/Server.cpp.o: in function `std::thread::thread<void (Server::*)(descript_socket), Server*, descript_socket&, void>(void (Server::*&&)(descript_socket), Server*&&, descript_socket&)':
Server.cpp:(.text._ZNSt6threadC2IM6ServerFv15descript_socketEJPS1_RS2_EvEEOT_DpOT0_[_ZNSt6threadC5IM6ServerFv15descript_socketEJPS1_RS2_EvEEOT_DpOT0_]+0x4f): undefined reference to `pthread_create'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/Server.dir/build.make:99:Server] 错误 1
make[1]: *** [CMakeFiles/Makefile2:76:CMakeFiles/Server.dir/all] 错误 2
make: *** [Makefile:84:all] 错误 2

根据保错信息undefined reference to `pthread_create’ 推测和linux下pthread有关
解决方法如下:在cmake最后两段加上find_package(Threads REQUIRED)
target_link_libraries(项目名称 Threads::Threads) 如下:

cmake_minimum_required(VERSION 3.10)
project(Server)


set(SERVER_INC ./include)
message(STATUS,"SERVER_INC is ${SERVER_INC}")
include_directories(${SERVER_INC})
file(GLOB H_FILE ${SERVER_INC}/*.h)
message(STATUS,"H_FILE is ${H_FILE}")
set(SOURCE 
                main.cpp
                Server.cpp
                ${H_FILE})
message(STATUS,"SOURCE is ${SOURCE}")
add_executable(${PROJECT_NAME} ${SOURCE})   

#新增如下代码
find_package(Threads REQUIRED) 
target_link_libraries(${PROJECT_NAME} Threads::Threads)

成功运行如下

STATUS,"SERVER_INC is ./include"
STATUS,"H_FILE is /home/lx/my-codes/C++/Others/Socket/Server/./include/Server.h"
STATUS,"SOURCE is main.cppServer.cpp/home/lx/my-codes/C++/Others/Socket/Server/./include/Server.h"
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE  
-- Configuring done
-- Generating done
-- Build files have been written to: /home/lx/my-codes/C++/Others/Socket/Server
[ 33%] Linking CXX executable Server
[100%] Built target Server
服务端socket创建
服务端bind绑定成功
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值