使用 WinSock2 开发,使用 CreateThread() 函数出错
Developing with WinSock2, error with CreateThread() function
我开始开发我的工具,它在TCP级别与net一起工作,并遇到了以下问题:
- 为 Winsock 的 accept(( 函数创建线程
我已经用谷歌搜索并查找了参考资料,并且每个地方都有有关创建新线程的信息:
- 它必须在前缀中包含 DWORD WINAPI(无符号长__stdcall(
- 它必须接受 LPVOID 参数
并且这样的函数将用作 CreateThread(( 函数中的第 3 个参数作为LPTHREAD_START_ROUTINE结构。
但是编译后我遇到了下一个错误:
(131(:错误 C2664:"创建线程":无法将参数 3 从"DWORD (__stdcall Net::* ((LPVOID("转换为"LPTHREAD_START_ROUTINE">
这是我的代码:
#include <iostream>
#include <Windows.h>
#pragma comment(lib, "Ws2_32.lib")
typedef struct Header
{
friend struct Net;
private:
WORD wsa_version;
WSAData wsa_data;
SOCKET sock;
SOCKADDR_IN service;
char *ip;
unsigned short port;
public:
Header(void)
{
wsa_version = 0x202;
ip = "0x7f.0.0.1";
port = 0x51;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr(ip);
service.sin_port = htons(port);
}
} Header;
typedef struct Net
{
private:
int result;
void WSAInit(WSAData *data, WORD *wsa_version)
{
result = WSAStartup(*wsa_version, &(*data));
if(result != NO_ERROR)
{
std::cout << "WSAStartup() failed with the error: " << result << std::endl;
}
else
{
std::cout << (*data).szDescription << " " << (*data).szSystemStatus << std::endl;
}
}
void SocketInit(SOCKET *my_socket)
{
(*my_socket) = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if((*my_socket) == INVALID_SOCKET)
{
std::cout << "Socket initialization failed with the error: " << WSAGetLastError() << std::endl;
WSACleanup();
}
else
{
std::cout << "Socket initialization successful!" << std::endl;
}
}
void SocketBind(SOCKET *my_socket, SOCKADDR_IN *service)
{
result = bind((*my_socket), (SOCKADDR*)&(*service), sizeof(*service));
if(result == SOCKET_ERROR)
{
std::cout << "Socket binding failed with the error: " << WSAGetLastError() << std::endl;
closesocket((*my_socket));
WSACleanup();
}
else
{
std::cout << "Socket binding successful!" << std::endl;
}
result = listen(*my_socket, SOMAXCONN);
if(result == SOCKET_ERROR)
{
std::cout << "Socket listening failed with the error: " << WSAGetLastError() << std::endl;
}
else
{
std::cout << "Listening to the socket..." << std::endl;
}
}
void SocketAccept(SOCKET *my_socket)
{
SOCKET sock_accept = accept((*my_socket), 0, 0);
if(sock_accept == INVALID_SOCKET)
{
std::cout << "Accept failed with the error: " << WSAGetLastError() << std::endl;
closesocket(*my_socket);
WSACleanup();
}
else
{
std::cout << "Client socket connected!" << std::endl;
}
char data[0x400];
result = recv(sock_accept, data, sizeof(data), 0);
}
DWORD WINAPI Threading(LPVOID lpParam)
{
SOCKET *my_socket = (SOCKET*)lpParam;
SocketAccept(my_socket);
}
public:
Net(void)
{
Header *obj_h = new Header();
WSAInit(&obj_h->wsa_data, &obj_h->wsa_version);
SocketInit(&obj_h->sock);
SocketBind(&obj_h->sock, &obj_h->service);
HANDLE thrd = CreateThread(NULL, 0, &Net::Threading, &obj_h->sock, 0, NULL);
delete &obj_h;
}
} Net;
int main(void)
{
Net *obj_net = new Net();
delete &obj_net;
return 0;
}
不能使用非静态成员函数C++。
使用静态的
Nestal的答案是正确的 - CreateThread需要一个函数,而不是一个方法。也就是说,这个样本还有很多其他问题,我不知道只是把它留在那里是否是负责任的事情。
首先,编码风格很奇怪:该示例名义上是用C++编写的,但实际上看起来像一个 C 程序。如果你要费心从C切换到C++,那么请注意,像这样使用"朋友"是一个强烈的暗示,表明你"做错了"。
直接传递对友元类属性的引用的奇怪风格有助于隐藏实际的代码问题:即使一旦它的构建也会失败很多,因为有许多竞争条件:套接字,作为引用传递给线程:&obj_h->sock
将在Threading
仍在运行时被删除。即使它没有被删除,它(以及从多个线程引用的任何变量(也应该被限定为volatile
,以确保编译器不会优化实际将变量保存到内存中。
即使你已经使线程进程"静态",安全地传递了参数,整理了竞争条件,并正确地易失限定了任何共享变量,你也需要添加线程同步来保护对共享变量的访问。同样,所呈现的代码样式(直接传递对值的引用(使得很难知道何时可以从不同的线程读取和写入变量 - 使得同步策略难以一致地实现。
祝你好运。
- 使用函数"remove"删除重复元素
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- 如何在其他文件中使用函数
- C++关于指针和使用函数将它们启动到堆的行为究竟是什么?
- 是否可以使用函数指针调用虚拟析构函数?
- 使用函数 c++ 集
- 错误:在第 6 行'{'标记之前,此处不允许使用函数定义
- 如何使用函数将一个对象的输入复制到另一个对象中
- 使用函数指针转发声明作为 lamba 声明
- 如何在使用 C 函数时测试C++代码
- 文本 RPG - 使用函数检查有效的输入
- 重载加法运算符(使用函数向对象添加字符串)
- 是否可以使用函数指针数组来删除分支
- 如何使用函数(而不是构造函数)将派生类对象分配给基类指针
- QObject::连接不起作用 - 使用函数语法找不到信号
- 使用函数引用指向节点的指针删除链表中的节点?
- 使用函数模板推导返回类型
- 使用函数重载输入运算符
- 是否可以使用函数返回的值初始化数组
- 在命名空间内使用函数的循环包含