gpt4 book ai didi

c - UDP 客户端未收到 UDP 服务器消息

转载 作者:太空宇宙 更新时间:2023-11-04 02:40:30 28 4
gpt4 key购买 nike

海友我是一个学习winsock2的新手。以下是我的udp服务器和客户端程序。

我这个程序客户端不知道服务器的IP地址,只知道端口。但是服务器会在整个网络中广播一条消息。

当客户端收到消息时,它会回溯服务器的 ip 并连接到它。

我的服务器和客户端在编译时都没有显示错误。

但是在执行客户端的 recvfrom() 语句时显示错误以下是我的代码的一部分。

服务器代码:

#include "stdafx.h"
#include<stdio.h>
#include<WinSock2.h>
#pragma comment (lib,"ws2_32.lib")

DWORD WINAPI UDPCONN(LPVOID x)
{
SOCKET s=(SOCKET)x;
char bro[200]="I am SERVER";
struct sockaddr_in hum;
hum.sin_family=AF_INET;
hum.sin_addr.s_addr=INADDR_BROADCAST;
hum.sin_port=htons(8888);
while (1)
{
if(sendto(s,bro,sizeof(bro),0,(struct sockaddr *)&hum,sizeof(hum))==SOCKET_ERROR)
{
printf("\nBroadcast failed ERROR CODE : %d\n",WSAGetLastError());
exit(1);
}
}
}

int _tmain(int argc, _TCHAR* argv[])
{
SOCKET s;
struct sockaddr_in hum;
int opt=1;

//Initializing winsock2
WSADATA wsa;
if((WSAStartup(MAKEWORD(2,2),&wsa))!=0)
{
printf("\nWinsock Not initialized ERROR CODE : %d\n",WSAGetLastError());
return 1;
}

//UDP Socket Creation
if((s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))==INVALID_SOCKET)
{
printf("\nUDP Socket not created ERROR CODE : %d\n",WSAGetLastError());
WSACleanup();
return 1;
}

//socket defenition
hum.sin_family=AF_INET;
hum.sin_addr.s_addr=INADDR_ANY;
hum.sin_port=htons(8888);

//Broadcast permission
if((setsockopt(s,SOL_SOCKET,SO_BROADCAST,(char *)&opt,sizeof(opt)))<0)
{
printf("\nBroadcast permissions failed ERROR CODE : %d\n",WSAGetLastError());
WSACleanup();
return 1;
}

//UDP SOCKET Binding
if((bind(s,(sockaddr *)&hum,sizeof(hum)))==SOCKET_ERROR)
{
printf("\nUDP socket binding failed ERROR CODE :%d\n",WSAGetLastError());
WSACleanup();
return 1;
}

//UDP connection thread
DWORD th;
CreateThread(NULL,0,UDPCONN,(LPVOID)s,0,&th);

客户端代码:

#include "stdafx.h"
#include <stdio.h>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")

int _tmain(int argc, _TCHAR* argv[])
{
//UDP Data
int slen;
char message[300];
int opt=1;
SOCKET s;
struct sockaddr_in sent;

//Initializing winsock
WSADATA wsa;
if((WSAStartup(MAKEWORD(2,2),&wsa))!=0)
{
printf("\nFailed Initializing Winsock EROR CODE : %d\n",WSAGetLastError());
return 1;
}

//UDP Socket creation
if((s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))== SOCKET_ERROR)
{
printf("\nUDP socket creation failed ERROR CODE :%d\n",WSAGetLastError());
WSACleanup();
return 1;
}

//UDP Broadcast permissions
if((setsockopt(s,SOL_SOCKET,SO_BROADCAST,(char *)&opt,sizeof(opt)))<0)
{
printf("\nERROR in broadcasting ERROR CODE : %d \n",WSAGetLastError());
WSACleanup();
return 1;
}

//UDP socket definition
sent.sin_family=AF_INET;
sent.sin_addr.s_addr=INADDR_ANY;
sent.sin_port=htons(8888);

//UDP Receiving broadcasted data
slen=sizeof(sent);
//fflush(stdout);
memset(message,'\0',300);
if((recvfrom(s,message,sizeof(message),0,(struct sockaddr *)&sent,&slen))<0)
{
printf("\nUDP Broadcast not received ERROR CODE : %d\n",WSAGetLastError());
WSACleanup();
return 1;
}
puts("\nGot server broadcast\n");
puts("\nTracing server ip\n");
getpeername(s,(sockaddr *)&sent,&slen);

...
}

这里我的客户抛出一个错误

UDP Broadcast not received ERROR CODE : 10022

错误代码10022的描述:参数无效。

提供了一些无效的参数(例如,为 setsockopt 函数指定了一个无效的级别)。在某些情况下,它还指套接字的当前状态——例如,在未监听的套接字上调用 accept。

根据错误描述,recvfrom() 函数中的参数之一无效。但是我找不到无效的参数。

请帮我清除错误。

最佳答案

如果您阅读 recvfrom() documentation ,它会告诉您确切您在客户端代码中出现错误的原因:

Parameters

s [in]
A descriptor identifying a bound socket.

...

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.

在调用 recvfrom() 之前,您没有在套接字上调用 bind()。更重要的是,当客户端和服务器在同一台机器上运行时,您不能将它们 bind() 到相同的 IP/端口。更改您广播到的端口,然后让客户端绑定(bind)到该端口。

此外,recvfrom() 的最后两个参数为您提供了数据报发送方的 IP/端口。它们不是用于指定网络适配器来读取数据报。在这种情况下,您不需要使用 getpeername()

您的代码还有一些其他问题:

在客户端,socket() 在失败时返回 INVALID_SOCKET,而不是 SOCKET_ERROR

在服务器端,您真的不应该使用 INADDR_BROADCAST。您应该将服务器套接字 bind() 到特定的网络适配器,然后 sendto() 其特定的子网广播 IP,您可以使用 GetAdaptersInfo()GetAdaptersAddresses()

并且在双方,如果 WSAStartup() 失败,则不能使用 WSAGetLastError(),这就是 WSAStartup() 返回错误的原因直接上代码。在调用 WSACleanup();

之前您没有关闭套接字

试试这个:

服务器代码:

#include "stdafx.h"
#include <stdio.h>
#include <WinSock2.h>
#pragma comment (lib,"ws2_32.lib")

DWORD WINAPI UDPCONN(LPVOID x)
{
SOCKET s = (SOCKET)x;
char bro[200] = "I am SERVER";
struct sockaddr_in hum;

memset(&hum, 0, sizeof(addr));
hum.sin_family = AF_INET;
hum.sin_addr.s_addr = INADDR_BROADCAST; // TODO: replace with subnet broadcast IP
hum.sin_port = htons(8887);

while (1)
{
if (sendto(s, bro, sizeof(bro), 0, (struct sockaddr *)&hum, sizeof(hum)) == SOCKET_ERROR)
{
printf("\nBroadcast failed ERROR CODE : %d\n", WSAGetLastError());
return 1;
}
}

return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
SOCKET s;
struct sockaddr_in hum;
int err, opt=1;

//Initializing winsock2
WSADATA wsa;
err = WSAStartup(MAKEWORD(2,2), &wsa);
if (err != 0)
{
printf("\nWinsock Not initialized ERROR CODE : %d\n", err);
return 1;
}

//UDP Socket Creation
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (s == INVALID_SOCKET)
{
printf("\nUDP Socket not created ERROR CODE : %d\n", WSAGetLastError());
WSACleanup();
return 1;
}

//socket defenition
memset(&hum, 0, sizeof(hum));
hum.sin_family = AF_INET;
hum.sin_addr.s_addr = INADDR_ANY; // TODO: replace with a specific NIC IP
hum.sin_port = htons(8888);

//Broadcast permission
if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt)) == SOCKET_ERROR)
{
printf("\nBroadcast permissions failed ERROR CODE : %d\n", WSAGetLastError());
closesocket(s);
WSACleanup();
return 1;
}

//UDP SOCKET Binding
if (bind(s, (sockaddr *)&hum, sizeof(hum)) == SOCKET_ERROR)
{
printf("\nUDP socket binding failed ERROR CODE : %d\n", WSAGetLastError());
closesocket(s);
WSACleanup();
return 1;
}

//UDP connection thread
DWORD th;
HANDLE hThread = CreateThread(NULL,0, UDPCONN, s, 0, &th);
if (!hThread)
{
printf("\nUDP thread failed ERROR CODE : %u\n", GetLastError());
closesocket(s);
WSACleanup();
return 1;
}

// do other things, wait for thread to terminate ...

DWORD exitCode = 0;
GetExitCodeThread(hThread, &exitCode);
CloseHandle(hThread);

closesocket(s);
WSACleanup();

return exitCode;
}

客户端代码:

#include "stdafx.h"
#include <stdio.h>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")

int _tmain(int argc, _TCHAR* argv[])
{
//UDP Data
int addrlen, msglen;
char message[300];
int err, opt=1;
SOCKET s;
struct sockaddr_in hum, addr;

//Initializing winsock
WSADATA wsa;
err = WSAStartup(MAKEWORD(2,2), &wsa);
if (err != 0)
{
printf("\nFailed Initializing Winsock EROR CODE : %d\n", err);
return 1;
}

//UDP Socket creation
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (s == INVALID_SOCKET)
{
printf("\nUDP socket creation failed ERROR CODE : %d\n", WSAGetLastError());
closesocket(s);
WSACleanup();
return 1;
}

//UDP Broadcast permissions
if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt)) == SOCKET_ERROR)
{
printf("\nERROR in broadcasting ERROR CODE : %d \n", WSAGetLastError());
closesocket(s);
WSACleanup();
return 1;
}

//UDP socket definition
memset(&hum, 0, sizeof(addr));
hum.sin_family = AF_INET;
hum.sin_addr.s_addr = INADDR_ANY;
hum.sin_port = htons(8887);

//UDP SOCKET Binding
if (bind(s, (sockaddr *)&hum, sizeof(hum)) == SOCKET_ERROR)
{
printf("\nUDP socket binding failed ERROR CODE : %d\n", WSAGetLastError());
closesocket(s);
WSACleanup();
return 1;
}

//UDP Receiving broadcasted data
addrlen = sizeof(addr);
msglen = recvfrom(s, message, sizeof(message), 0, (struct sockaddr *)&addr, &addrlen);
if (msglen == SOCKET_ERROR)
{
printf("\nUDP Broadcast not received ERROR CODE : %d\n", WSAGetLastError());
closesocket(s);
WSACleanup();
return 1;
}

printf("\nGot server broadcast\n");
printf("\nServer ip: %s, port: %hu\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
printf("\nMessage: %.*s\n", msglen, message);

...
}

关于c - UDP 客户端未收到 UDP 服务器消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32471004/

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