gpt4 book ai didi

c++ - winsock2:recvfrom() 函数以错误 10022(无效参数)结束

转载 作者:行者123 更新时间:2023-11-28 04:54:55 32 4
gpt4 key购买 nike

我正在使用 C++ 开发一个 UDP 套接字,它既是客户端又是服务器。我正在使用 Visual Studio 2017 并在 Windows 7 上运行它。我在使用 recvfrom() 函数时遇到了一些问题,它以“无效参数”错误结尾。我认为 socket 没问题,sockaddr_in 结构没问题,线程没问题,甚至带有 sendto() 函数的 while 循环也没问题。但是线程在调用一个recvfrom()函数后结束,我真的不知道问题出在哪里......

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <thread>

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

using namespace std;

void printMessage(SOCKET s, SOCKADDR_IN destAddr) {

char message[100];
int result, error;
int addrSize = sizeof(destAddr);
do {
printf("som v threade\n");
result = recvfrom(s, message, 100, 0, (SOCKADDR*)&destAddr, &addrSize);
printf("%d\n", result);

if (result < 0) {
error = WSAGetLastError();
printf("%d\n", error);
}

if (result > 0)
printf("%s", message);

} while (result > 0);

}


int main(int argc, char *argv[]) {

WORD dllVersion = MAKEWORD(2, 1);
WSADATA wsaData;

if (WSAStartup(dllVersion, &wsaData) != 0) {
printf("Winsock startup failed");
exit(1);
}

const char *ip = "127.0.0.1";
int dstPort = 49999;
int srcPort = 49999;

SOCKADDR_IN destaddr, srcaddr;
SOCKET s;
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

if (s < 0) {
printf("Error creating socket");
exit(1);
}

destaddr.sin_family = AF_INET;
destaddr.sin_addr.s_addr = inet_addr(ip);
destaddr.sin_port = htons(dstPort);

srcaddr.sin_family = AF_INET;
srcaddr.sin_addr.s_addr = htonl(INADDR_ANY);
srcaddr.sin_port = htons(srcPort);


bind(s, (SOCKADDR*)&srcaddr, sizeof(srcaddr));

thread receiving (printMessage, s, destaddr);
receiving.detach();

while (1) {
char message[100];

printf("Write a message:");
scanf("%s", message);

if (sendto(s, message, sizeof(message), 0, (SOCKADDR *) &destaddr, sizeof(destaddr)) < 0) {
printf("Message not sent");
exit(1);
}
}
return 0;
}

最佳答案

错误代码 10022 是 WSAEINVAL。根据 recvfrom()文档:

WSAEINVAL

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() 函数开始。 WinSock 和 STL 都有自己的 bind() 函数,但是你的 use of using namespace std masks that fact .

此外,每次调用 recvfrom() 时都需要重置 addrSize,因为它可能会修改值。它希望您传入最大缓冲区大小,然后输出实际写入缓冲区的大小。

此外,您没有在正确的时间调用 WSAGetLastError()。您需要在 WinSock 调用失败后立即调用它,然后再任何 操作。换句话说,不要在调用 WSAGetLastError() 之前调用 printf(),因为它可能会重置错误代码。

此外,如果 recvfrom() 读取成功,则您假设数据以 null 终止,但这并不能保证。您需要将 result 作为参数传递给 printf()

而且,您真的不应该将 C 风格的 I/O 与 C++ 混合使用。请改用 C++ 样式的 I/O。

尝试更像这样的东西:

#include <iostream>
#include <string>
#include <thread>
#include <winsock2.h>

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

void printMessage(SOCKET s)
{
char message[100];
int result, error, addrSize;
SOCKADDR_IN clientaddr;

do {
std::cout << "som v threade" << std::endl;
addrSize = sizeof(clientaddr);
result = recvfrom(s, message, 100, 0, (SOCKADDR*)&clientaddr, &addrSize);
if (result == SOCKET_ERROR) {
error = WSAGetLastError();
std::cout << "Receive failed. Error: " << error << std::endl;
continue;
}
std::cout << "Received " << result << " byte(s) from " << inet_ntoa(clientaddr.sin_addr) << ":" << ntohs(clientaddr.sin_port) << std::endl;
if (result > 0) {
std::cout.write(message, result);
std::cout << std::endl;
}
}
while (result > 0);
}

int main(int argc, char *argv[]) {
WORD dllVersion = MAKEWORD(2, 1);
WSADATA wsaData;
int result, error;

result = WSAStartup(dllVersion, &wsaData);
if (result != 0) {
std::cout << "Winsock startup failed. Error: " << result << std::endl;
exit(1);
}

SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (s == INVALID_SOCKET) {
error = WSAGetLastError();
std::cout << "Socket creation failed. Error: " << error << std::endl;
exit(1);
}

const char *ip = "127.0.0.1";
unsigned short dstPort = 49999;
unsigned short srcPort = 49999;

SOCKADDR_IN destaddr = {};
SOCKADDR_IN srcaddr = {};

destaddr.sin_family = AF_INET;
destaddr.sin_addr.s_addr = inet_addr(ip);
destaddr.sin_port = htons(dstPort);

srcaddr.sin_family = AF_INET;
srcaddr.sin_addr.s_addr = INADDR_ANY;
srcaddr.sin_port = htons(srcPort);

result = ::bind(s, (SOCKADDR*)&srcaddr, sizeof(srcaddr));
if (result == SOCKET_ERROR) {
error = WSAGetLastError();
std::cout << "Socket bind failed. Error: " << error << std::endl;
exit(1);
}

std::thread receiving(printMessage, s);
receiving.detach();

std::string message;
do {
std::cout << "Write a message: ";
std::getline(std::cin, message);
result = sendto(s, message.c_str(), message.size(), 0, (SOCKADDR *) &destaddr, sizeof(destaddr));
if (result == SOCKET_ERROR) {
error = WSAGetLastError();
std::cout << "Message not sent. Error: " << error << std::endl;
exit(1);
}
}
while (true);

return 0;
}

关于c++ - winsock2:recvfrom() 函数以错误 10022(无效参数)结束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47383826/

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