本人在编写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绑定成功
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)