gpt4 book ai didi

c - 多线程时recvfrom()返回错误10022(C)

转载 作者:行者123 更新时间:2023-11-30 16:23:47 25 4
gpt4 key购买 nike

我是套接字编程和多线程的新手,我仍在学习它,但我有一个无法解决的问题,在其他一些主题上我找到了一些答案,但他们看起来没有和我一样的问题。

我想创建一个 UDP 客户端。该客户端应该能够发送 (sendto()) 和接收 (recvfrom())。

我正在对发送和接收函数进行多线程处理,但当我调用 WSAGetLastError() 时,recvfrom() 返回错误 10022。

我使用库 pthread.h 进行多线程,使用 winsock2.h 进行套接字。

当我不使用多线程时,没有问题。

我的代码:

    #include <sys/types.h>
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

#pragma comment(lib,"ws2_32.lib")

#define SERVER "127.0.0.1"
#define PORT 8888
#define MAXBUFFER 1024

void Sending(void *VarThread);
void Receiving(void *VarThread);

int main(int argc, char **argv)
{
int sock;
pthread_t Thread_ID_1;
pthread_t Thread_ID_2;

WSADATA WSAData;
WSAStartup(MAKEWORD(2, 0), &WSAData);


sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1)
{
perror("\nsocket()");
printf("%d", WSAGetLastError());
exit(0);
}

pthread_create(&Thread_ID_1, NULL, Sending, (void *)&sock);
pthread_create(&Thread_ID_2, NULL, Receiving, (void *)&sock);

pthread_join(Thread_ID_1, NULL);
pthread_join(Thread_ID_2, NULL);

close(sock);
WSACleanup();
return 0;
}

void Sending(void *VarThread)
{
int sock = *(int *)VarThread;
int i;

struct sockaddr_in si;
si.sin_family = AF_INET;
si.sin_addr.s_addr = inet_addr(SERVER);
si.sin_port = htons(PORT);

char buff[MAXBUFFER];
ssize_t message;

while(1)
{
fgets(buff, MAXBUFFER, stdin);
for(i = 1; i < MAXBUFFER; i++) // delete the last '\n'
{
if(buff[i] == '\0')
{
buff[i - 1] = '\0';
i = MAXBUFFER;
}
}
message = sendto(sock, buff, MAXBUFFER, 0, (struct sockaddr *)&si, sizeof(si));
if (message == -1)
{
perror("\nsendto()");
printf("%d", WSAGetLastError());
}
}
}


void Receiving(void *VarThread)
{
int sock = *(int *)VarThread;
char buff[MAXBUFFER];
ssize_t recu;

while(1)
{
recu = recvfrom(sock, buff, MAXBUFFER, 0, NULL, 0);
if(recu == -1)
{
perror("\n\nError recvfrom ");
printf("Error Code : %d", WSAGetLastError());
}
else
{
printf("message = %s\n", buff);
}
}
}

(我的机器上还运行着一个乒乓服务器来测试代码)

当我启动此应用程序时,recvfrom() 不会阻塞并返回错误 10022,直到我使用 Sending() 函数。正是当我使用 fgets() 时,recvfrom() 停止返回错误。

如何阻止此错误发生?

P.S.:我的机器运行的是 Windows 10。

编辑:

我尝试过其他方法,我在函数 Receiving() 中使用 bind() 但它不起作用,这是我的代码:

void *Receiving(void *VarThread)
{
int sock = *(int *)VarThread;
struct sockaddr_in SockRecv;
int slen = sizeof(SockRecv);
char buff[MAXBUFFER];
ssize_t recu;




memset((char *)&SockRecv, 0, sizeof(SockRecv));
SockRecv.sin_family = AF_INET;
SockRecv.sin_addr.s_addr = htonl(SERVER);
SockRecv.sin_port = htons(PORT);

if(bind(sock, (struct sockaddr *)&SockRecv, sizeof(SockRecv)) == -1)
{
perror("\n\nbind()");
printf("Error Code : %d", WSAGetLastError());
exit(0);
}




while(1)
{
recu = recvfrom(sock, buff, MAXBUFFER, 0, (struct sockaddr *)&SockRecv, &slen);
if(recu == -1)
{
perror("\n\nError recvfrom()");
printf("Error Code : %d", WSAGetLastError());
}
else
{
printf("Message = %s\n", buff);
}
}
}

最佳答案

错误 10022 是 WSAEINVALThe microsoft documentation of recvfrom指定由该函数引起时的含义(强调我的):

The socket has not been bound with bind, or an unknown flag was specified, or MSG_OOB was specified for a socket with SO_OOBINLINE enabled, or (for byte stream-style sockets only) len was zero or negative.

您尝试在第二个代码片段中绑定(bind)它有一个不同的问题。您应该在启动任一线程之前绑定(bind)套接字,以避免接收线程中的绑定(bind)与作为发送一部分的隐式绑定(bind)之间的竞争条件。

虽然您没有明确指定绑定(bind)的使用如何失败,但我的猜测是添加绑定(bind)代码将接收者延迟了足够长的时间,以便让发送者首先绑定(bind),之后接收者的绑定(bind)失败,因为您不能两次绑定(bind)套接字.

关于c - 多线程时recvfrom()返回错误10022(C),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53895036/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com