【Windows】【C++】【Udp】 udp通信协议详解和示例
在 Windows 平台上,使用 C++ 实现的 UDP 通信服务器和客户端示例代码稍有不同,因为 Windows 使用 Winsock API 进行网络编程。下面是一个简单的 UDP 服务器和客户端的实现示例,包括详细的代码和说明。
UDP 服务器代码示例(Windows)
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib") // 链接 Winsock 库
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
// 初始化 Winsock
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
std::cerr << "Winsock initialization failed" << std::endl;
return -1;
}
// 创建套接字
SOCKET sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sockfd == INVALID_SOCKET) {
std::cerr << "Socket creation failed" << std::endl;
WSACleanup();
return -1;
}
// 设置服务器地址结构
struct sockaddr_in serverAddr, clientAddr;
memset(&serverAddr, 0, sizeof(serverAddr));
memset(&clientAddr, 0, sizeof(clientAddr));
serverAddr.sin_family = AF_INET; // IPv4
serverAddr.sin_addr.s_addr = INADDR_ANY; // 任意地址
serverAddr.sin_port = htons(PORT); // 端口号
// 绑定套接字到地址
if (bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
std::cerr << "Bind failed" << std::endl;
closesocket(sockfd);
WSACleanup();
return -1;
}
std::cout << "UDP Server is up and listening on port " << PORT << std::endl;
while (true) {
char buffer[BUFFER_SIZE];
int clientAddrLen = sizeof(clientAddr);
int n = recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&clientAddr, &clientAddrLen);
if (n == SOCKET_ERROR) {
std::cerr << "recvfrom failed" << std::endl;
continue;
}
buffer[n] = '\0'; // 添加字符串结束符
std::cout << "Received: " << buffer << std::endl;
// 发送回应给客户端
sendto(sockfd, buffer, n, 0, (struct sockaddr*)&clientAddr, clientAddrLen);
std::cout << "Echoed back to client" << std::endl;
}
closesocket(sockfd);
WSACleanup();
return 0;
}
UDP 客户端代码示例(Windows)
#include <iostream>
#include <string>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib") // 链接 Winsock 库
#define PORT 8080
#define SERVER_IP "127.0.0.1"
#define BUFFER_SIZE 1024
int main()
{
// 初始化 Winsock
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
std::cerr << "Winsock initialization failed" << std::endl;
return -1;
}
// 创建套接字
SOCKET sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sockfd == INVALID_SOCKET) {
std::cerr << "Socket creation failed" << std::endl;
WSACleanup();
return -1;
}
// 设置服务器地址结构
struct sockaddr_in serverAddr;
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET; // IPv4
serverAddr.sin_port = htons(PORT); // 端口号
inet_pton(AF_INET, SERVER_IP, &serverAddr.sin_addr); // 服务器 IP
while (true) {
std::string message;
std::cout << "Enter message: ";
std::getline(std::cin, message);
// 发送消息到服务器
sendto(sockfd, message.c_str(), message.size(), 0, (const struct sockaddr*)&serverAddr, sizeof(serverAddr));
// 接收服务器的回应
char buffer[BUFFER_SIZE];
int serverAddrLen = sizeof(serverAddr);
int n = recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&serverAddr, &serverAddrLen);
if (n == SOCKET_ERROR) {
std::cerr << "recvfrom failed" << std::endl;
continue;
}
buffer[n] = '\0'; // 添加字符串结束符
std::cout << "Server: " << buffer << std::endl;
}
closesocket(sockfd);
WSACleanup();
return 0;
}
代码详解
-
头文件包含:
winsock2.h
和ws2tcpip.h
是 Windows 中网络编程需要的头文件。- 使用
#pragma comment(lib, "ws2_32.lib")
语句链接 Winsock 库。
-
初始化 Winsock:
- 在进行任何其他网络操作之前,我们需要调用
WSAStartup()
来初始化 Winsock 库。
- 在进行任何其他网络操作之前,我们需要调用
-
套接字创建:
- 使用
socket()
函数创建一个 UDP 套接字,返回一个套接字描述符。
- 使用
-
地址结构配置:
- 服务器地址配置
INADDR_ANY
表示监听来自任意 IP 的数据,端口号固定为 8080。 - 客户端设定目标服务器的 IP 地址和端口号。
- 服务器地址配置
-
绑定套接字:
- 使用
bind()
函数将创建的套接字与指定地址和端口绑定。
- 使用
-
数据接收和发送:
- 服务器使用
recvfrom()
函数接收数据,并使用sendto()
函数将数据回传给客户端。 - 客户端发送数据后,使用
recvfrom()
接收服务器的回应。
- 服务器使用
-
清理资源:
- 最后使用
closesocket()
关闭套接字,调用WSACleanup()
清理 Winsock 资源。
- 最后使用
编译和运行
要编译这些代码,通常在 Windows 上使用 Visual Studio 或者在命令行中使用以下命令(假设使用 g++ 编译器):
g++ udp_server.cpp -o udp_server -lws2_32
g++ udp_client.cpp -o udp_client -lws2_32
./udp_server
./udp_client
测试
- 启动 UDP 服务器,它会开始监听来自客户端的消息。
- 之后启动 UDP 客户端,输入消息并按下回车键,消息会发送到服务器,并收到服务器返回的回显信息。
以上是一个简单的 Windows 平台下的 UDP 通信的实现,希望对你有所帮助。如果你有进一步的问题,请随时提问!