c 中的 IPv6 服务器 - 接收失败



我用winsock2.h为IPv6服务器编写了一个小型c程序 当我在Visual Studio中运行该程序时,我总是收到以下消息: 接收自失败

我只是在 recvfrom 函数中找不到错误。也许有人可以看到为什么我的程序在这一点上不起作用,谢谢! :-)

此致敬意 眼界

#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma comment(lib, "Ws2_32.lib")
int main(int argc, char* argv[]) {
SOCKET server_socket;
struct sockaddr_in6 server_addr, client_addr;
socklen_t client_len;
char buf[1024];
char clientIP[256];
WSADATA data;
WORD version = MAKEWORD(2, 2);
if (WSAStartup(version, &data) == SOCKET_ERROR) {
printf("WSASStartup failedn");
WSACleanup();
exit(EXIT_FAILURE);
}
server_socket = socket(AF_INET6, SOCK_DGRAM, 0);
if (server_socket == -1) {
printf("creating socket failedn");
WSACleanup();
exit(EXIT_FAILURE);
}
else {
printf("creating socket successfuln");
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin6_addr = in6addr_any;
server_addr.sin6_family = AF_INET6;
server_addr.sin6_port = htons(5001);
if (bind(server_socket, (const struct sockaddr*) & server_addr,
sizeof(server_addr)) == -1) {
printf("bind socket failedn");
WSACleanup();
exit(EXIT_FAILURE);
}
else {
printf("bind socket successfuln");
}
while (1) {
memset(&client_addr, 0, sizeof(client_addr));
memset(buf, 0, sizeof(buf));
if (recvfrom(server_socket, (char*)buf, 1024, 0,
(struct sockaddr*) & client_addr,
sizeof(client_addr)) == -1) {
printf("recvfrom failedn");
WSACleanup();
exit(EXIT_FAILURE);
}
else {
printf("recvfrom successful");
}
printf("%sn", buf);
printf("IP: %sn", inet_ntop(AF_INET6, &client_addr.sin6_addr,
clientIP, 256));
}
closesocket(server_socket);
WSACleanup();
return 0;
}

您滥用了recvfrom()fromlen参数期望接收指向intint*指针,该指针在输入时指定在from参数中传递的sockaddr缓冲区的字节大小,在输出时接收写入from缓冲区的sockaddr的字节大小。

代码中还有一些其他小错误:

  • WSAStartup()失败时不返回SOCKET_ERROR,而是返回实际的错误代码。

  • 您忽略了recvfrom()的返回值,它告诉您实际写入buf的字节数。 您假设buf在将其传递给printf("%s")时总是以 null 终止,但这并不能保证。 您正在清零buf以使用 null 终止符对其进行初始化,如果recvfrom()收到包含少于 1024 个字节的数据报,这很好。但是,如果它收到的数据报正好是 1024 字节,那么您的所有空终止符都将被覆盖,并且没有终止符可供printf()查找(如果recvfrom()收到超过 1024 字节的数据报,它将失败并出现WSAEMSGSIZE错误,这不是致命错误,但您将其视为错误(。您可以传递recvfrom()的返回值以printf()缓冲区大小,而不是完全依赖任何 null 终止符。无需浪费开销来清零recvfrom()将覆盖的内容。

试试这个:

#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma comment(lib, "Ws2_32.lib")
int main(int argc, char* argv[]) {
SOCKET server_socket;
struct sockaddr_in6 server_addr, client_addr;
int client_len, num_recvd;
char buf[1024];
char clientIP[256];
WSADATA data;
WORD version = MAKEWORD(2, 2);
int errCode = WSAStartup(version, &data);
if (errCode != 0) {
printf("WSAStartup failed, error %dn", errCode);
WSACleanup();
return EXIT_FAILURE;
}
server_socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
if (server_socket == INVALID_SOCKET) {
errCode = WSAGetLastError();
printf("creating socket failed, error %dn", errCode);
WSACleanup();
return EXIT_FAILURE;
}
printf("creating socket successfuln");
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin6_addr = in6addr_any;
server_addr.sin6_family = AF_INET6;
server_addr.sin6_port = htons(5001);
if (bind(server_socket, (struct sockaddr*) &server_addr, sizeof(server_addr)) == SOCKET_ERROR) {
errCode = WSAGetLastError();
printf("bind socket failed, error %dn", errCode);
closesocket(server_socket);
WSACleanup();
return EXIT_FAILURE;
}
printf("bind socket successfuln");
while (1) {
client_len = sizeof(client_addr);
num_recvd = recvfrom(server_socket, buf, sizeof(buf), 0, (struct sockaddr*) &client_addr, &client_len);
if (num_recvd == SOCKET_ERROR) {
errCode = WSAGetLastError();
if (errCode != WSAEMSGSIZE) {
printf("recvfrom failed, error %dn", errCode);
closesocket(server_socket);
WSACleanup();
return EXIT_FAILURE;
}
printf("recvfrom truncated a datagram larger than %u bytes!n", sizeof(buf));
num_recvd = sizeof(buf);
}
else {
printf("recvfrom successfuln");
}
printf("%.*sn", num_recvd, buf);
printf("IP: %sn", inet_ntop(AF_INET6, &client_addr.sin6_addr, clientIP, 256));
}
closesocket(server_socket);
WSACleanup();
return 0;
}

最新更新