如何从线程中的不同模块调用函数?
how does one call a function from a diffrent module in a thread?
我正在尝试使用套接字创建一个多线程服务器。 每个用户都会打开一个新线程。 这个线程运行一个函数,该函数最终需要从不同的模块调用另一个函数,但是当它到达它应该调用的函数时,我总是收到运行时错误。 有什么想法吗?
void Server::accept()
{
// notice that we step out to the global namespace
// for the resolution of the function accept
// this accepts the client and create a specific socket from server to this client
SOCKET client_socket = ::accept(_serverSocket, NULL, NULL);
if (client_socket == INVALID_SOCKET)
throw std::exception(__FUNCTION__);
std::cout << "Client accepted. Server and client can speak" << std::endl;
// the function that handle the conversation with the client
std::thread lol(&Server::clientHandler, this, std::ref(client_socket));
lol.detach();
}
void Server::clientHandler(SOCKET clientSocket)
{
try
{
std::cout << "IM HERE";
int userMessageType = 0;
int sizeOfUserName = 0;
int totalUserLen = 0;
std::string loginReply = "";
std::set<std::string> ::iterator itr;
std::string allNames = "";
while (userMessageType != MT_CLIENT_EXIT)
{
char buffer[2048];
std::cout << "IM HERE";
buffer[2047] = 0;
std::cout << "IM HERE";
userMessageType = Helper::getMessageTypeCode(clientSocket); // code crashes here!!
std::cout << "ASDSAD";
std::cout << "CODE " << userMessageType << std::endl;
switch (userMessageType)
{
case MT_CLIENT_LOG_IN:
{
sizeOfUserName = Helper::getIntPartFromSocket(clientSocket, 2);
std::string user = Helper::getStringPartFromSocket(clientSocket, sizeOfUserName);
std::cout << user << std::endl;
loginReply += "1010000000";
for (itr = onlineUsers.begin(); itr != onlineUsers.end(); itr++)
{
totalUserLen = totalUserLen + (int)(((*itr).length()));
allNames += *itr;
allNames += "&";
std::cout << "n" << allNames << "n";
}
if (totalUserLen != 0)
{
std::cout << "ASD" << allNames.size();
allNames[allNames.size() - 1] = ' ';
std::cout << "ASD";
allNames = allNames.substr(0, allNames.size() - 1);
std::cout <<"n" << allNames << "qqq";
for (int i = 0; i < 5 - allNames.length(); i++)
{
}
loginReply += std::to_string(allNames.length());
std::cout << loginReply;
Helper::sendData(clientSocket, loginReply);
}
else
{
loginReply += "00000";
Helper::sendData(clientSocket, loginReply);
std::cout << "ASD";
}
onlineUsers.insert(user);
}
case MT_CLIENT_UPDATE:
{
std::string;
}
case MT_CLIENT_EXIT:
{
closesocket(clientSocket);
return;
}
}
}
closesocket(clientSocket);
}
catch (const std::exception& e)
{
closesocket(clientSocket);
}
}
最小生殖示例: 助手:
#include "Helper.h"
#include <iostream>
#include <fstream>
#include <iomanip>
#include <sstream>
using std::string;
// recieves the type code of the message from socket (3 bytes)
// and returns the code. if no message found in the socket returns 0 (which means the client disconnected)
int Helper::getMessageTypeCode(SOCKET sc)
{
char* s = getPartFromSocket(sc, 3);
std::string msg(s);
if (msg == "")
return 0;
int res = std::atoi(s);
delete s;
return res;
}
void Helper::send_update_message_to_client(SOCKET sc, const string& file_content, const string& second_username, const string &all_users)
{
//TRACE("all users: %sn", all_users.c_str())
const string code = std::to_string(MT_SERVER_UPDATE);
const string current_file_size = getPaddedNumber(file_content.size(), 5);
const string username_size = getPaddedNumber(second_username.size(), 2);
const string all_users_size = getPaddedNumber(all_users.size(), 5);
const string res = code + current_file_size + file_content + username_size + second_username + all_users_size + all_users;
//TRACE("message: %sn", res.c_str());
sendData(sc, res);
}
// recieve data from socket according byteSize
// returns the data as int
int Helper::getIntPartFromSocket(SOCKET sc, int bytesNum)
{
char* s = getPartFromSocket(sc, bytesNum, 0);
return atoi(s);
}
// recieve data from socket according byteSize
// returns the data as string
string Helper::getStringPartFromSocket(SOCKET sc, int bytesNum)
{
char* s = getPartFromSocket(sc, bytesNum, 0);
string res(s);
return res;
}
// return string after padding zeros if necessary
string Helper::getPaddedNumber(int num, int digits)
{
std::ostringstream ostr;
ostr << std::setw(digits) << std::setfill('0') << num;
return ostr.str();
}
// recieve data from socket according byteSize
// this is private function
char* Helper::getPartFromSocket(SOCKET sc, int bytesNum)
{
return getPartFromSocket(sc, bytesNum, 0);
}
char* Helper::getPartFromSocket(SOCKET sc, int bytesNum, int flags)
{
if (bytesNum == 0)
{
return (char*)"";
}
char* data = new char[bytesNum + 1];
int res = recv(sc, data, bytesNum, flags);
if (res == INVALID_SOCKET)
{
std::string s = "Error while recieving from socket: ";
s += std::to_string(sc);
throw std::exception(s.c_str());
}
data[bytesNum] = 0;
return data;
}
// send data to socket
// this is private function
void Helper::sendData(SOCKET sc, std::string message)
{
const char* data = message.c_str();
if (send(sc, data, message.size(), 0) == INVALID_SOCKET)
{
throw std::exception("Error while sending message to client");
}
}
SOCKET
是整型的类型定义,因此您应该std::ref( client_socket )
部分替换为client_socket
。
此外,对Server::clientHandler
的线程访问也不会同步。这不是一个好的解决方案,但为了防止竞争条件,您可以执行以下操作。
void Server::clientHandler(SOCKET clientSocket)
{
static std::mutex thread_safe;
// Guarantees that only one thread proceeds at a time
std::lock_guard<std::mutex> lock { thread_safe };
....
....
相关文章:
- 如何从线程中的不同模块调用函数?
- 没有头文件如何使用c ++调用其他模块中的函数?
- C++-在没有自定义.lib文件的情况下从Lua C模块调用Lua函数
- 从 C# 模块调用C++函数引发随机崩溃
- 无法使用 JNI 从C++模块成功调用 Java 函数
- 如何在 lua cpp 模块中调用托管 c++ dll 函数
- 为什么无法在 Cocoa 应用程序调用的 C++ func 中嵌入自定义 Python 模块
- Cython c++模块,多次调用构造函数
- 无法从 Python C API 中内置的模块调用方法
- numpy.core.multiarray在通过Xcode中开发的C 应用程序调用Python模块时未能导入
- 如何在LLVM传递中的模块末尾插入函数调用?
- 在C++中嵌入Python:在Python脚本中导入模块在一个函数调用过程中有效,但在另一个调用过程中无效
- 在另一个应用程序中嵌入python时,如何在子模块(即scipy.optimize.nnls)中导入或调用函数
- 另一个子模块错误的 omnet 访问方法 - 调用 'check_and_cast(cModule*&)' 没有匹配函数
- 节点.JS,C++模块:为什么当我尝试调用本地的长度方法时出现段错误<Array>?
- 带有嵌入式 Python 的 Python 扩展模块调用了错误的库
- 从不同模块调用函数 - 引用错误
- 带有SWIG的Python C++扩展-通过导入模块调用函数
- asm.js模块.调用/模块.cwrap回调
- 从另一个模块调用基类构造函数