C 线程采用插座参数
C++ Threading which takes a SOCKET parameter
我目前正在研究我的高级项目,并且该项目几乎完成了,但是我需要在2010年在VisualStudio 2010中实现多线程,而该项目不支持C 11。因此,我将其用作多线程的来源(由我的讲师建议)在如何用插座实现它的情况下,我完全丢失了。
我的问题是如何将我已经编码的套接字与多线程使用。以下是我到目前为止所拥有的。
typedef struct SenderData {
SOCKET socConnection;
} SENDERDATA, *PSENDERDATA;
DWORD WINAPI SenderThreadFunction( LPVOID lpParam){
HANDLE hStdout;
PSENDERDATA pDataArray;
TCHAR msgBuf[BUF_SIZE];
size_t cchStringSize;
DWORD dwChars;
// Make sure there is a console to receive output results.
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if( hStdout == INVALID_HANDLE_VALUE )
return 1;
// Cast the parameter to the correct data type.
// The pointer is known to be valid because
// it was checked for NULL before the thread was created.
pDataArray = (PSENDERDATA)lpParam;
return 0;
}
此功能具有所有命令,可以在telnet中启动会话并从文件发送消息
DWORD WINAPI Sender(LPVOID lpParam){
}
以下创建连接,我最初在main()中都有它,但不确定现在将其放置在哪里
WSADATA wsaData; // Creates wsaData object
WSAStartup(MAKEWORD(2, 2), &wsaData); //Initializes Winsock
//Creates the socket object named "soc(Connection"
SOCKET socConnection = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKADDR_IN Addr;
HOSTENT* Host = gethostbyname("smtp.com");
Addr.sin_addr.s_addr = inet_addr(inet_ntoa(*(in_addr*)Host->h_addr_list[0]));
Addr.sin_family = AF_INET;
Addr.sin_port = htons(25);
如果我不使用螺纹
,这将在main()中被调用if (connect(Connection, (SOCKADDR*)&Addr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
cout << "Connection Failed" << endl;
在main()中执行以下代码时,我将如何放置先前的代码?我对C 非常新,我非常感谢任何帮助。预先感谢您。
hThreadArray[0] = CreateThread(
NULL, // default security attributes
0, // use default stack size
Sender, // thread function name
pDataArray[0], // argument to thread function
0, // use default creation flags
&dwThreadIdArray[0]); // returns the thread identifier
要在线程中运行的代码需要在您传递给CreateThread()
的Sender()
函数内。因此,这将是您的所有插座调用(WSAStartup()
和WSACleanup()
除外,只能称呼一次)。
类似的东西:
DWORD WINAPI Sender( LPVOID lpParam)
{
// Make sure there is a console to receive output results.
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if( hStdout == INVALID_HANDLE_VALUE )
return 1;
HOSTENT* Host = gethostbyname("smtp.com");
if (!Host)
{
cout << "Unable to resolve smtp.com" << endl;
return 1;
}
//Creates the socket object named "soc(Connection"
SOCKET socConnection = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (socConnection == INVALID_SOCKET)
{
cout << "Socket Failed" << endl;
return 1;
}
SOCKADDR_IN Addr = {0};
Addr.sin_family = AF_INET;
Addr.sin_addr = * (in_addr*) Host->h_addr_list[0];
Addr.sin_port = htons(25);
if (connect(socConnection, (SOCKADDR*)&Addr, sizeof(Addr)) == SOCKET_ERROR)
{
cout << "Connection Failed" << endl;
closesocket(socConnection);
return 1;
}
...
closesocket(socConnection);
return 0;
}
int main()
{
WSADATA wsaData; // Creates wsaData object
WSAStartup(MAKEWORD(2, 2), &wsaData); //Initializes Winsock
DWORD dwThreadId;
HANDLE hThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
&Sender, // thread function name
NULL, // argument to thread function
0, // use default creation flags
&dwThreadId);
...
WaitForSingleObject(hThread, INFINITE);
DWORD ExitCode = 0;
GetExitCodeThread(hThread, &ExitCode);
CloseHandle(hThread);
if (ExitCode != 0)
{
...
}
...
WSACleanup();
return 0;
}
,以及如何将线程封装到类中,以获取真正面向对象的和更可重复使用的代码:
#include <windows.h>
#include <stdio.h>
#include <assert.h>
class CThread
{
public:
void Start()
{
assert(!m_Handle);
DWORD thread_id;
m_Handle = ::CreateThread(NULL, 0, StaticThreadProc, this, 0, &thread_id);
// this should be a fatal error/exit instead of a simple assert...
assert(m_Handle);
}
void Join()
{
assert(m_Handle);
::WaitForSingleObject(m_Handle, INFINITE);
}
protected:
virtual void Execute() = 0;
CThread() : m_Handle(NULL) {}
~CThread()
{
if (m_Handle)
{
Join();
::CloseHandle(m_Handle);
m_Handle = NULL;
}
}
private:
static DWORD WINAPI StaticThreadProc(LPVOID param)
{
CThread* thread = reinterpret_cast<CThread*>(param);
thread->Execute();
return 0;
}
private:
HANDLE m_Handle;
};
class CMyThread : public CThread
{
public:
CMyThread()
{
m_Sock = NULL;
m_Whatever = 0;
m_OtherParam = 0;
m_Result = 0;
}
// Use this to initialize the parameters for your thread before starting it...
// You could initialize from your constructor too if you wouldn't store your
// threads in an array by value...
void Init(SOCKET sock, int whatever_parameter_you_need, int other_param)
{
m_Sock = sock;
m_Whatever = whatever_parameter_you_need;
m_OtherParam = other_param;
}
int GetResult() const
{
return m_Result;
}
protected:
virtual void Execute() override
{
// Use m_Sock, m_Whatever, m_OtherParam ....
// Fill out m_Result before returning from the Execute() method of the thread.
// You can also create the socket inside the thread if you want,
// noone forces you to pass it here as an init parameter.
m_Result = 5;
}
private:
SOCKET m_Sock;
int m_Whatever;
int m_OtherParam;
int m_Result;
};
int main()
{
// TODO: network init (WSAStartup)
const int NUM_THREADS = 3;
CMyThread threads[NUM_THREADS];
// 1. Initializing threads with incoming parameters to work with
for (int i=0; i<NUM_THREADS; ++i)
{
//threads[i].Init(...)
}
// 2. Starting threads
for (int i=0; i<NUM_THREADS; ++i)
threads[i].Start();
// 3. Waiting for threads to finish...
for (int i=0; i<NUM_THREADS; ++i)
threads[i].Join();
// 4. Processing results if needed
int result0 = threads[0].GetResult();
printf("%dn", result0);
// TODO: Network Cleanup (WSACleanup)
return 0;
}
相关文章:
- 如何反转整数参数包
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用默认参数等选择模板专业化
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 函数调用中参数的顺序重要吗
- 部分定义/别名模板模板参数
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 使用不带参数的函数访问结构元素
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 如何使用Luacneneneba API正确读取字符串和表参数
- 在派生函数中指定void*参数
- 视图中的参数推导失败:take_while
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- 使用指向成员的指针将成员函数作为参数传递
- RECV插座类型参数的问题
- C 线程采用插座参数