Winsock2 线程参数引发异常访问冲突
Winsock2 thread arguments throw exception access violation
我正在使用 WinSock2.h
编写 UDP 服务器-客户端程序,其中各个线程所需的参数(SOCKET
、sockaddr_in
)通过结构传递给线程。
我的接收函数在到达 recvfrom()
部分时一直抛出异常,但只有在我调试程序时才会抛出异常。如果我在没有调试器的情况下启动它,它不会显示任何错误也不会停止程序 运行。此异常仅发生在 服务器 端。此外,recvfrom()
错误检查不断在客户端抛出错误 10022,但据我了解,这是由于客户端没有 bind()
造成的。
服务器端是否存在 bind()
在另一个函数中的问题,或者我的指针哪里有问题?我不知道为什么它只在服务器端抛出异常。
typedef struct thread_args {
struct sockaddr_in sockaddr;
SOCKET socket;
int keep_alive_count;
}THREAD_ARG;
void* receive_packets(void* arguments) {
THREAD_ARG* args = (THREAD_ARG*)arguments;
struct sockaddr_in* from;
char buffer[MAX_FRAGMENTATION + sizeof(HEADER)];
HEADER* message;
while (1) {
memset(buffer, "[=10=]", MAX_FRAGMENTATION + sizeof(HEADER));
//this is where I get the exception thrown
if (recvfrom(args->socket, buffer, sizeof(buffer), 0, (struct sockaddr*) & from, sizeof(from)) == SOCKET_ERROR) {
printf("recvfrom() failed, error code: %d\n", WSAGetLastError());
exit(RECVFAIL);
}
message = (HEADER*)buffer;
char flag = message->flags;
}
}
return 0;
}
int client(THREAD_ARG* args) {
u_short port;
char ip[50];
struct sockaddr_in client_sock;
void* return_value1, *return_value2;
getchar();
printf("Please enter the IP address you would like to communicate with:\n");
gets(IP);
printf("Please enter the port number you would like to communicate with:\n");
scanf("%hu", &port);
client_sock.sin_family = AF_INET;
client_sock.sin_addr.s_addr = inet_addr(IP);
client_sock.sin_port = htons(port);
args->sockaddr = client_sock;
pthread_t send_thread, receive_thread, keep_alive_thread;
pthread_create(&send_thread, NULL, send_packets, args);
pthread_create(&receive_thread, NULL, receive_packets, args);
pthread_create(&keep_alive_thread, NULL, keep_alive, args);
pthread_join(send_thread, &return_value1);
pthread_join(receive_thread, &return_value2);
pthread_join(keep_alive_thread, NULL);
return 0;
}
int server(THREAD_ARG* args) {
u_short port;
int valid;
struct sockaddr_in server_sock;
void* return_value1, * return_value2;
printf("Please enter the port number you would like to listen on:\n");
scanf("%hu", &port);
server_sock.sin_family = AF_INET;
server_sock.sin_addr.s_addr = INADDR_ANY;
server_sock.sin_port = htons(port);
if(bind(args->socket, (struct sockaddr_in*) & server_sock, sizeof(server_sock)) == SOCKET_ERROR) {
printf("Bind failed, error code: %d\n", WSAGetLastError());
return 1;
}
printf("Bind done\n");
args->sockaddr = server_sock;
pthread_t receive_thread;
pthread_create(&receive_thread, NULL, receive_packets, args);
pthread_join(receive_thread, &return_value2);
}
int main() {
WSADATA was;
SOCKET sock;
char choice;
THREAD_ARG* args;
printf("WinSock initialisation.\n");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
printf("WinSock initialisation failed. Error code: %d\n", WSAGetLastError());
return 1;
}
printf("WinSock initialised.");
if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
printf("Couldn't create socket: %d\n", WSAGetLastError());
}
printf("Socket created.\n");
printf("Would you like to be a server or a client?\n");
printf("1 - Server\n");
printf("2 - Client\n");
printf("0 - Exit\n");
args = (THREAD_ARG*)malloc(sizeof(THREAD_ARG));
args->socket = sock;
switch (choice = getchar())
{
case '0':
return 0;
case '1':
server(args);
break;
case '2':
client(args);
break;
default:
printf("Please choose from above\n");
}
return 0;
}
struct sockaddr_in* from;
char buffer[MAX_FRAGMENTATION + sizeof(HEADER)];
HEADER* message;
你这里有问题。你只分配了一个sockaddr_in*
。但是你需要一个实际的 sockaddr_in
来保存地址。
while (1) {
memset(buffer, "[=11=]", MAX_FRAGMENTATION + sizeof(HEADER));
这里,memset
的第二个参数是错误的。它应该是要设置的值,而不是指向值的指针。
if (recvfrom(args->socket, buffer, sizeof(buffer), 0, (struct sockaddr*) & from, sizeof(from)) == SOCKET_ERROR) {
在这里,您将 struct sockaddr_in **
转换为 struct sockaddr *
,丢掉了一个间接级别。那没有任何意义。最后一个参数 sizeof(from)
是 指针 的大小。这是不对的。
THREAD_ARG* args;
...
args = (THREAD_ARG*)malloc(sizeof(THREAD_ARG));
args->socket = sock;
为什么这个奇怪的间接?为什么不只是 THREAD_ARD args;
并摆脱 malloc
和 ->
东西?
我正在使用 WinSock2.h
编写 UDP 服务器-客户端程序,其中各个线程所需的参数(SOCKET
、sockaddr_in
)通过结构传递给线程。
我的接收函数在到达 recvfrom()
部分时一直抛出异常,但只有在我调试程序时才会抛出异常。如果我在没有调试器的情况下启动它,它不会显示任何错误也不会停止程序 运行。此异常仅发生在 服务器 端。此外,recvfrom()
错误检查不断在客户端抛出错误 10022,但据我了解,这是由于客户端没有 bind()
造成的。
服务器端是否存在 bind()
在另一个函数中的问题,或者我的指针哪里有问题?我不知道为什么它只在服务器端抛出异常。
typedef struct thread_args {
struct sockaddr_in sockaddr;
SOCKET socket;
int keep_alive_count;
}THREAD_ARG;
void* receive_packets(void* arguments) {
THREAD_ARG* args = (THREAD_ARG*)arguments;
struct sockaddr_in* from;
char buffer[MAX_FRAGMENTATION + sizeof(HEADER)];
HEADER* message;
while (1) {
memset(buffer, "[=10=]", MAX_FRAGMENTATION + sizeof(HEADER));
//this is where I get the exception thrown
if (recvfrom(args->socket, buffer, sizeof(buffer), 0, (struct sockaddr*) & from, sizeof(from)) == SOCKET_ERROR) {
printf("recvfrom() failed, error code: %d\n", WSAGetLastError());
exit(RECVFAIL);
}
message = (HEADER*)buffer;
char flag = message->flags;
}
}
return 0;
}
int client(THREAD_ARG* args) {
u_short port;
char ip[50];
struct sockaddr_in client_sock;
void* return_value1, *return_value2;
getchar();
printf("Please enter the IP address you would like to communicate with:\n");
gets(IP);
printf("Please enter the port number you would like to communicate with:\n");
scanf("%hu", &port);
client_sock.sin_family = AF_INET;
client_sock.sin_addr.s_addr = inet_addr(IP);
client_sock.sin_port = htons(port);
args->sockaddr = client_sock;
pthread_t send_thread, receive_thread, keep_alive_thread;
pthread_create(&send_thread, NULL, send_packets, args);
pthread_create(&receive_thread, NULL, receive_packets, args);
pthread_create(&keep_alive_thread, NULL, keep_alive, args);
pthread_join(send_thread, &return_value1);
pthread_join(receive_thread, &return_value2);
pthread_join(keep_alive_thread, NULL);
return 0;
}
int server(THREAD_ARG* args) {
u_short port;
int valid;
struct sockaddr_in server_sock;
void* return_value1, * return_value2;
printf("Please enter the port number you would like to listen on:\n");
scanf("%hu", &port);
server_sock.sin_family = AF_INET;
server_sock.sin_addr.s_addr = INADDR_ANY;
server_sock.sin_port = htons(port);
if(bind(args->socket, (struct sockaddr_in*) & server_sock, sizeof(server_sock)) == SOCKET_ERROR) {
printf("Bind failed, error code: %d\n", WSAGetLastError());
return 1;
}
printf("Bind done\n");
args->sockaddr = server_sock;
pthread_t receive_thread;
pthread_create(&receive_thread, NULL, receive_packets, args);
pthread_join(receive_thread, &return_value2);
}
int main() {
WSADATA was;
SOCKET sock;
char choice;
THREAD_ARG* args;
printf("WinSock initialisation.\n");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
printf("WinSock initialisation failed. Error code: %d\n", WSAGetLastError());
return 1;
}
printf("WinSock initialised.");
if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
printf("Couldn't create socket: %d\n", WSAGetLastError());
}
printf("Socket created.\n");
printf("Would you like to be a server or a client?\n");
printf("1 - Server\n");
printf("2 - Client\n");
printf("0 - Exit\n");
args = (THREAD_ARG*)malloc(sizeof(THREAD_ARG));
args->socket = sock;
switch (choice = getchar())
{
case '0':
return 0;
case '1':
server(args);
break;
case '2':
client(args);
break;
default:
printf("Please choose from above\n");
}
return 0;
}
struct sockaddr_in* from;
char buffer[MAX_FRAGMENTATION + sizeof(HEADER)];
HEADER* message;
你这里有问题。你只分配了一个sockaddr_in*
。但是你需要一个实际的 sockaddr_in
来保存地址。
while (1) {
memset(buffer, "[=11=]", MAX_FRAGMENTATION + sizeof(HEADER));
这里,memset
的第二个参数是错误的。它应该是要设置的值,而不是指向值的指针。
if (recvfrom(args->socket, buffer, sizeof(buffer), 0, (struct sockaddr*) & from, sizeof(from)) == SOCKET_ERROR) {
在这里,您将 struct sockaddr_in **
转换为 struct sockaddr *
,丢掉了一个间接级别。那没有任何意义。最后一个参数 sizeof(from)
是 指针 的大小。这是不对的。
THREAD_ARG* args;
...
args = (THREAD_ARG*)malloc(sizeof(THREAD_ARG));
args->socket = sock;
为什么这个奇怪的间接?为什么不只是 THREAD_ARD args;
并摆脱 malloc
和 ->
东西?