c 中的 IPv6 服务器 - recvfrom 失败
IPv6 Server in c - recvfrom failed
我用 winsock2.h 为 IPv6 服务器编写了一个小的 c 程序当我 运行 Visual Studio 中的程序时,我一直收到以下消息:recvfrom 失败
我只是找不到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 failed\n");
WSACleanup();
exit(EXIT_FAILURE);
}
server_socket = socket(AF_INET6, SOCK_DGRAM, 0);
if (server_socket == -1) {
printf("creating socket failed\n");
WSACleanup();
exit(EXIT_FAILURE);
}
else {
printf("creating socket successful\n");
}
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 failed\n");
WSACleanup();
exit(EXIT_FAILURE);
}
else {
printf("bind socket successful\n");
}
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 failed\n");
WSACleanup();
exit(EXIT_FAILURE);
}
else {
printf("recvfrom successful");
}
printf("%s\n", buf);
printf("IP: %s\n", inet_ntop(AF_INET6, &client_addr.sin6_addr,
clientIP, 256));
}
closesocket(server_socket);
WSACleanup();
return 0;
}
您在滥用 recvfrom()
。 fromlen
参数期望收到一个指向 int
的 int*
指针,它在输入时指定 sockaddr
缓冲区的字节大小被传递到 from
参数,并在输出上接收写入 from
缓冲区的 sockaddr
的字节大小。
您的代码中还有其他一些小错误:
WSAStartup()
不会 return SOCKET_ERROR
失败,它 return 是一个实际的错误代码。
您忽略了 recvfrom()
的 return 值,它告诉您实际写入了 buf
的字节数。您假设 buf
在将其传递给 printf("%s")
时始终以 null 结尾,但这并不能保证。您正在将 buf
清零以使用空终止符对其进行初始化,如果 recvfrom()
接收到包含少于 1024 字节的数据报,这很好。但是,如果它接收到一个正好有 1024 字节的数据报,那么所有的空终止符都将被覆盖,并且 printf()
将找不到任何终止符(如果 recvfrom()
接收到一个超过 1024 字节的数据报,它会因 WSAEMSGSIZE
错误而失败,这不是致命错误,但您将其视为致命错误)。您可以将 recvfrom()
的 return 值传递给 printf()
作为缓冲区大小,而不是完全依赖任何空终止符。无需浪费开销将 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 %d\n", 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 %d\n", errCode);
WSACleanup();
return EXIT_FAILURE;
}
printf("creating socket successful\n");
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 %d\n", errCode);
closesocket(server_socket);
WSACleanup();
return EXIT_FAILURE;
}
printf("bind socket successful\n");
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 %d\n", 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 successful\n");
}
printf("%.*s\n", num_recvd, buf);
printf("IP: %s\n", inet_ntop(AF_INET6, &client_addr.sin6_addr, clientIP, 256));
}
closesocket(server_socket);
WSACleanup();
return 0;
}
我用 winsock2.h 为 IPv6 服务器编写了一个小的 c 程序当我 运行 Visual Studio 中的程序时,我一直收到以下消息:recvfrom 失败
我只是找不到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 failed\n");
WSACleanup();
exit(EXIT_FAILURE);
}
server_socket = socket(AF_INET6, SOCK_DGRAM, 0);
if (server_socket == -1) {
printf("creating socket failed\n");
WSACleanup();
exit(EXIT_FAILURE);
}
else {
printf("creating socket successful\n");
}
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 failed\n");
WSACleanup();
exit(EXIT_FAILURE);
}
else {
printf("bind socket successful\n");
}
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 failed\n");
WSACleanup();
exit(EXIT_FAILURE);
}
else {
printf("recvfrom successful");
}
printf("%s\n", buf);
printf("IP: %s\n", inet_ntop(AF_INET6, &client_addr.sin6_addr,
clientIP, 256));
}
closesocket(server_socket);
WSACleanup();
return 0;
}
您在滥用 recvfrom()
。 fromlen
参数期望收到一个指向 int
的 int*
指针,它在输入时指定 sockaddr
缓冲区的字节大小被传递到 from
参数,并在输出上接收写入 from
缓冲区的 sockaddr
的字节大小。
您的代码中还有其他一些小错误:
WSAStartup()
不会 returnSOCKET_ERROR
失败,它 return 是一个实际的错误代码。您忽略了
recvfrom()
的 return 值,它告诉您实际写入了buf
的字节数。您假设buf
在将其传递给printf("%s")
时始终以 null 结尾,但这并不能保证。您正在将buf
清零以使用空终止符对其进行初始化,如果recvfrom()
接收到包含少于 1024 字节的数据报,这很好。但是,如果它接收到一个正好有 1024 字节的数据报,那么所有的空终止符都将被覆盖,并且printf()
将找不到任何终止符(如果recvfrom()
接收到一个超过 1024 字节的数据报,它会因WSAEMSGSIZE
错误而失败,这不是致命错误,但您将其视为致命错误)。您可以将recvfrom()
的 return 值传递给printf()
作为缓冲区大小,而不是完全依赖任何空终止符。无需浪费开销将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 %d\n", 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 %d\n", errCode);
WSACleanup();
return EXIT_FAILURE;
}
printf("creating socket successful\n");
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 %d\n", errCode);
closesocket(server_socket);
WSACleanup();
return EXIT_FAILURE;
}
printf("bind socket successful\n");
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 %d\n", 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 successful\n");
}
printf("%.*s\n", num_recvd, buf);
printf("IP: %s\n", inet_ntop(AF_INET6, &client_addr.sin6_addr, clientIP, 256));
}
closesocket(server_socket);
WSACleanup();
return 0;
}