如何在 c++ 中使用 winsock 接收 udp 数据包
How do I receive udp packets with winsock in c++?
为了尝试将我的头缠绕在udp套接字上,我试图将本教程页面中的代码移植到winsock http://www.linuxhowtos.org/C_C++/socket.htm(如果重要的话,在win 8上运行)。[以下直接链接]
代码当前编译并运行,但我从未收到数据包,两个程序都只是等待并阻止 recvfrom()。 我一直遇到同样的问题(例如,此代码 https://stackoverflow.com/a/679529/873217 的修改版本包含 recvfrom() 调用。使用此代码C++数据报 (UDP)winsocket 的问题,通过环回适配器在同一套接字上发送和接收,进行建议的更改)。 我想我犯了一些简单而根本的错误;但我无法自己找到它。 希望有更多经验的人可以为我阐明这个问题。谢谢。
附加说明:
我在同一台计算机上运行服务器 exe,然后运行客户端 exe。它连接到互联网。 我也尝试使用解析为我的 IP 地址的域。 我也尝试禁用防火墙,尽管我已经允许两个程序完全访问。
直接链接到原始客户端和服务器代码:
http://www.linuxhowtos.org/data/6/client_udp.chttp://www.linuxhowtos.org/data/6/server_udp.c
我目前的尝试:
两者都链接到libws2_32.a
客户端代码:
#include <stdio.h>
#include <winsock2.h>
#include <string.h>
void error(const char *);
int main()
{
WSAData data;
WSAStartup( MAKEWORD( 2, 2 ), &data );
int sock, n;
int length;
struct sockaddr_in server, from;
struct hostent *hp;
char buffer[256];
unsigned short serverPort = 27072;
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) error("socket");
server.sin_family = AF_INET;
hp = gethostbyname("localhost");//have also tried my url
if (hp==0) error("Unknown host");
memmove((char *)hp->h_addr, (char *)&server.sin_addr, hp->h_length);
server.sin_port = htons(serverPort);
length = sizeof(struct sockaddr_in);
printf("Please enter the message: ");
memset(buffer, 0, 256);
fgets(buffer, 255, stdin);
n = sendto (sock, buffer, strlen(buffer), 0, (const struct sockaddr *)&server, length);
if (n < 0) error("Sendto");
printf("sent %i bytesn", n);
n = recvfrom(sock, buffer, 256, 0, (struct sockaddr *)&server, &length);
if (n < 0) error("recvfrom");
//write(1,"Got an ack: ", 12);
//write(1, buffer, n);
printf("Got msg: %sn",buffer);
closesocket(sock);
WSACleanup();
return(0);
}
void error(const char *msg)
{
perror(msg);
exit(0);
}
服务器代码:
#include <stdio.h>
#include <winsock2.h>
#include <string.h>
void error(const char *);
int main()
{
WSAData data;
WSAStartup( MAKEWORD( 2, 2 ), &data );
int sock, length, n;
int fromlen;
struct sockaddr_in server;
struct sockaddr_in from;
char buf[1024];
unsigned short serverPort = 27072;
sock=socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) error("Opening socket");
length = sizeof(server);
memset(&server, 0, length);
server.sin_family = AF_INET;
server.sin_addr.s_addr=INADDR_ANY;
server.sin_port=htons(serverPort);
if (bind(sock,(struct sockaddr *)&server, length)<0) error ("binding");
fromlen = sizeof(struct sockaddr_in);
while(1)
{
n = recvfrom(sock, buf, 1024, 0, (struct sockaddr *)&from, &fromlen);
if (n<0) error("recvfrom");
//write(1,"Received a datagram: ", 21);
//write(1,buf,n);
printf("Received a datagram: %s", buf);
n = sendto(sock, "Got your messagen",17,0,(struct sockaddr *)&from,fromlen);
if (n<0)error("sendto");
}
closesocket(sock);
WSACleanup();
return 0;
}
void error (const char *msg)
{
perror(msg);
exit(0);
}
以下 UDP 测试应用程序在我的设置 - Windows 7、VS 2013 上正常工作。
我创建了一些轻量级包装类来进行资源管理,并将错误代码转换为异常。这使客户端和服务器代码更易于阅读。请务必先运行服务器。
网络.h
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <system_error>
#include <string>
#include <iostream>
#pragma once
class WSASession
{
public:
WSASession()
{
int ret = WSAStartup(MAKEWORD(2, 2), &data);
if (ret != 0)
throw std::system_error(WSAGetLastError(), std::system_category(), "WSAStartup Failed");
}
~WSASession()
{
WSACleanup();
}
private:
WSAData data;
};
class UDPSocket
{
public:
UDPSocket()
{
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock == INVALID_SOCKET)
throw std::system_error(WSAGetLastError(), std::system_category(), "Error opening socket");
}
~UDPSocket()
{
closesocket(sock);
}
void SendTo(const std::string& address, unsigned short port, const char* buffer, int len, int flags = 0)
{
sockaddr_in add;
add.sin_family = AF_INET;
add.sin_addr.s_addr = inet_addr(address.c_str());
add.sin_port = htons(port);
int ret = sendto(sock, buffer, len, flags, reinterpret_cast<SOCKADDR *>(&add), sizeof(add));
if (ret < 0)
throw std::system_error(WSAGetLastError(), std::system_category(), "sendto failed");
}
void SendTo(sockaddr_in& address, const char* buffer, int len, int flags = 0)
{
int ret = sendto(sock, buffer, len, flags, reinterpret_cast<SOCKADDR *>(&address), sizeof(address));
if (ret < 0)
throw std::system_error(WSAGetLastError(), std::system_category(), "sendto failed");
}
sockaddr_in RecvFrom(char* buffer, int len, int flags = 0)
{
sockaddr_in from;
int size = sizeof(from);
int ret = recvfrom(sock, buffer, len, flags, reinterpret_cast<SOCKADDR *>(&from), &size);
if (ret < 0)
throw std::system_error(WSAGetLastError(), std::system_category(), "recvfrom failed");
// make the buffer zero terminated
buffer[ret] = 0;
return from;
}
void Bind(unsigned short port)
{
sockaddr_in add;
add.sin_family = AF_INET;
add.sin_addr.s_addr = htonl(INADDR_ANY);
add.sin_port = htons(port);
int ret = bind(sock, reinterpret_cast<SOCKADDR *>(&add), sizeof(add));
if (ret < 0)
throw std::system_error(WSAGetLastError(), std::system_category(), "Bind failed");
}
private:
SOCKET sock;
};
服务器
#include "Network.h"
int main()
{
try
{
WSASession Session;
UDPSocket Socket;
char buffer[100];
Socket.Bind(100);
while (1)
{
sockaddr_in add = Socket.RecvFrom(buffer, sizeof(buffer));
std::string input(buffer);
std::reverse(std::begin(input), std::end(input));
Socket.SendTo(add, input.c_str(), input.size());
}
}
catch (std::system_error& e)
{
std::cout << e.what();
}
}
客户
#include "Network.h"
int main()
{
try
{
WSASession Session;
UDPSocket Socket;
std::string data = "hello world";
char buffer[100];
Socket.SendTo("127.0.0.1", 100, data.c_str(), data.size());
Socket.RecvFrom(buffer, 100);
std::cout << buffer;
}
catch (std::exception &ex)
{
std::cout << ex.what();
}
char c;
std::cin >> c;
}
好吧,我不确定winsock2.h在Windows和Linux中的工作方式是否相同,但是,在Windows中,当您创建套接字时,您必须设置正在使用的协议,TCP或UDP:
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
AF_INET = IPv4;SOCK_STREAM = TCP 的字节流;IPPROTO_TCP = TCP 协议。
对于UDP(我以前从未使用过),根据MSDN的说法,它将是:
SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
SOCK_DGRAM = UDP 的字节流;IPPROTO_UDP = UDP 协议。
该代码将在Windows中工作。我想在Linux中会是类似的。
- (Winsock) UDP 接收工作正常,但同一套接字的发送失败
- 使用 winsock 接收 http 请求
- 使用 WinSock 时接收SOCKET_ERROR
- Winsock 从服务器接收乱码数据
- Winsock 简单客户端服务器,接收失败
- 为什么我的android客户端无法接收到来自winsock c++服务器的字符串消息
- C++ WinSock Recv 在接收 0 数据时终止线程而不是返回错误代码
- C++TCP Winsock服务器多次接收相同的数据包
- Winsock正在接收额外的数据
- 未在客户端Winsock中接收到完整数据
- Winsock 单客户端服务器同时发送和接收
- C++服务器无法从客户端/Winsock 接收数据
- C++Winsock将冻结接收数据
- 使用winsock,如何从IE接收POST Http消息
- Winsock发送,接收-它们是如何工作的
- 为什么我的c++ Winsock服务器无法从客户端接收数据
- Winsock -读取、写入、发送和接收套接字的最佳方式
- 使用Winsock接收分块HTTP数据
- Winsock接收给乱码混合有用的html
- 如何在 c++ 中使用 winsock 接收 udp 数据包