agv-control/Plugin/KcCtrl/UdpSocket.cpp
2025-06-09 09:09:25 +08:00

198 lines
4.4 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "UdpSocket.h"
void UDPServer::cleanup() {
#ifdef _WIN32
if (serverSocket != INVALID_SOCKET) {
closesocket(serverSocket);
WSACleanup();
}
#else
if (serverSocket != INVALID_SOCKET) {
close(serverSocket);
}
#endif
}
UDPServer::UDPServer() : serverSocket(INVALID_SOCKET), initialized(false) {
#ifdef _WIN32
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
std::cerr << "WSAStartup failed\n";
return;
}
#endif
initialized = true;
}
UDPServer::~UDPServer() {
cleanup();
}
bool UDPServer::Start(int port) {
if (!initialized) return false;
serverSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (serverSocket == INVALID_SOCKET) {
std::cerr << "Create socket failed\n";
return false;
}
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(port);
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(serverSocket, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
std::cerr << "Bind failed\n";
return false;
}
return true;
}
// 修改后的接收方法UDPServer类
int UDPServer::Receive(char* buffer, int bufferSize, std::string& clientIP, int& clientPort) {
sockaddr_in clientAddr;
socklen_t clientAddrLen = sizeof(clientAddr);
int recvSize = recvfrom(serverSocket, buffer, bufferSize, 0,
(sockaddr*)&clientAddr, &clientAddrLen);
if (recvSize == SOCKET_ERROR) {
return -1;
}
// 使用跨平台的地址转换方法
char ipBuffer[INET_ADDRSTRLEN] = { 0 };
#ifdef _WIN32
InetNtopA(AF_INET, &clientAddr.sin_addr, ipBuffer, INET_ADDRSTRLEN);
#else
inet_ntop(AF_INET, &clientAddr.sin_addr, ipBuffer, INET_ADDRSTRLEN);
#endif
clientIP = ipBuffer;
clientPort = ntohs(clientAddr.sin_port);
return recvSize;
}
bool UDPServer::Send(const char* buffer, int bufferSize, const std::string& clientIP, int clientPort) {
sockaddr_in clientAddr;
clientAddr.sin_family = AF_INET;
clientAddr.sin_port = htons(clientPort);
inet_pton(AF_INET, clientIP.c_str(), &clientAddr.sin_addr);
int sentSize = sendto(serverSocket, buffer, bufferSize, 0,
(sockaddr*)&clientAddr, sizeof(clientAddr));
return sentSize == bufferSize;
}
void UDPServer::Close() {
cleanup();
serverSocket = INVALID_SOCKET;
}
/// <summary>
/// UDPClient
/// </summary>
void UDPClient::cleanup() {
#ifdef _WIN32
if (clientSocket != INVALID_SOCKET) {
closesocket(clientSocket);
WSACleanup();
}
#else
if (clientSocket != INVALID_SOCKET) {
close(clientSocket);
}
#endif
}
UDPClient::UDPClient() : clientSocket(INVALID_SOCKET), initialized(false) {
#ifdef _WIN32
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
std::cerr << "WSAStartup failed\n";
return;
}
#endif
initialized = true;
}
UDPClient::~UDPClient() {
cleanup();
}
bool UDPClient::Connect(const std::string& serverIP, int serverPort) {
if (!initialized) return false;
clientSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (clientSocket == INVALID_SOCKET) {
std::cerr << "Create socket failed\n";
return false;
}
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(serverPort);
inet_pton(AF_INET, serverIP.c_str(), &serverAddr.sin_addr);
return true;
}
bool UDPClient::Send(const char* buffer, int bufferSize) {
int sentSize = sendto(clientSocket, buffer, bufferSize, 0,
(sockaddr*)&serverAddr, sizeof(serverAddr));
return sentSize == bufferSize;
}
//lTimeoutMs 单位毫秒
int UDPClient::Receive(char* buffer, int bufferSize, int lTimeoutMs)
{
sockaddr_in fromAddr;
socklen_t fromLen = sizeof(fromAddr);
#ifdef _WIN32
int timeout = lTimeoutMs; // 转换为毫秒
setsockopt(clientSocket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
#else
struct timeval tv;
tv.tv_sec = lTimeoutMs / 1000;
tv.tv_usec = (lTimeoutMs % 1000) * 1000;
setsockopt(clientSocket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
#endif
int recvSize = recvfrom(clientSocket, buffer, bufferSize, 0,
(sockaddr*)&fromAddr, &fromLen);
return recvSize;
}
// sbuffer 发送数据
// sbufferSize 发送数据长度
// rbuffer 接收数据缓冲区
// rbufferSize 接收数据长度
// lRto 重传时间
// lRtoCnt 重传次数
// 返回值 接收数据长度,小于等于零表示发送以及重传都失败了
int UDPClient::SendAndRecv(const char* sbuffer, int sbufferSize, char* rbuffer, int rbufferSize, int lRto, int lRtoCnt)
{
do
{
if (!Send(sbuffer, sbufferSize))
{
continue;
}
int lRecvLen = Receive(rbuffer, rbufferSize, lRto);
if (lRecvLen > 0)
{
return lRecvLen;
}
} while (lRtoCnt-- > 0);
return -1;
}
void UDPClient::Close() {
cleanup();
clientSocket = INVALID_SOCKET;
}