一、c++
个人测试记录,有问题还请指出,谢谢
参考:C++开发基础之网络编程WinSock库使用详解TCP/UDP Socket开发_c++ udp使用什么库-CSDN博客
代码中Logger测试见文章: c++中spdlog的使用/python中logger的使用-CSDN博客
1、main.cpp
收发TCP信号:
#include <iostream>
#include <thread>
#include <vector>
#include "Logger.h"
#include "SocketManager.h"
#pragma warning(disable:4996)
int main() {
initLogger();
SocketManager socket_manager;
// 使用 std::thread 并传递成员函数的指针和对象实例的引用
std::thread t1(&SocketManager::get_from_tcp, &socket_manager, 11100);
// std::thread t2(&SocketManager::get_from_udp, &socket_manager, 11111);
std::thread t3(&SocketManager::send_to_tcp, &socket_manager, "123456", "127.0.0.1", 11100);
// std::thread t4(&SocketManager::send_to_udp, &socket_manager, "123456", "127.0.0.1", 11111);
t1.detach();
// t2.detach();
t3.detach();
// t4.detach();
Sleep(6000000);
return 0;
}
运行结果如下:
收发UDP信号:
#include <iostream>
#include <thread>
#include <vector>
#include "Logger.h"
#include "SocketManager.h"
#pragma warning(disable:4996)
int main() {
initLogger();
SocketManager socket_manager;
// 使用 std::thread 并传递成员函数的指针和对象实例的引用
// std::thread t1(&SocketManager::get_from_tcp, &socket_manager, 11100);
std::thread t2(&SocketManager::get_from_udp, &socket_manager, 11111);
// std::thread t3(&SocketManager::send_to_tcp, &socket_manager, "123456", "127.0.0.1", 11100);
std::thread t4(&SocketManager::send_to_udp, &socket_manager, "123456", "127.0.0.1", 11111);
// t1.detach();
t2.detach();
// t3.detach();
t4.detach();
Sleep(6000000);
return 0;
}
运行结果如下:
2、SocketManager.h
// #pragma once // 为确保在不同编译环境中使用,可以使用#define的方法
#ifndef SOCKETMANAGER_H
#define SOCKETMANAGER_H
#include <iostream>
#include <stdio.h>
#include <winsock2.h>
#include <string>
#include "Logger.h"
#pragma comment(lib, "ws2_32.lib")
#pragma warning(disable:4996)
std::string asciiToHex(const std::string& asciiStr); // 将ascii码转为十六进制
class SocketManager {
public:
SocketManager();
~SocketManager();
void initialization(); // 初始化套接字库
void get_from_udp(int); // 从客户端接收发来的udp信息
void get_from_tcp(int); // 从客户端接收发来的tcp信息
void send_to_tcp(std::string, std::string, int); // 向服务端发送tcp信息
void send_to_udp(std::string, std::string, int); // 向服务端发送udp信息
private:
//定义服务端套接字,接受请求套接字
SOCKET ListenSocket_UDP_get;
SOCKET ListenSocket_TCP_get;
SOCKET SendSocket_UDP_to;
SOCKET SendSocket_TCP_to;
//服务端/客户端地址
SOCKADDR_IN service_UDP_get;
SOCKADDR_IN service_TCP_get;
SOCKADDR_IN service_UDP_to;
SOCKADDR_IN service_TCP_to;
};
#endif // SOCKETMANAGER_H
3、SocketManager.cpp
#include "SocketManager.h"
SocketManager::SocketManager() {
ListenSocket_UDP_get = INVALID_SOCKET;
ListenSocket_TCP_get = INVALID_SOCKET;
SendSocket_UDP_to = INVALID_SOCKET;
SendSocket_TCP_to = INVALID_SOCKET;
}
SocketManager::~SocketManager() {
if (ListenSocket_UDP_get != INVALID_SOCKET) {
closesocket(ListenSocket_UDP_get);
WSACleanup();
}
if (ListenSocket_TCP_get != INVALID_SOCKET) {
closesocket(ListenSocket_TCP_get);
WSACleanup();
}
if (SendSocket_UDP_to != INVALID_SOCKET) {
closesocket(SendSocket_UDP_to);
WSACleanup();
}
if (SendSocket_TCP_to != INVALID_SOCKET) {
closesocket(SendSocket_TCP_to);
WSACleanup();
}
}
void SocketManager::get_from_udp(int port) {
// 初始化套接字库
initialization();
// 创建套接字
ListenSocket_UDP_get = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (ListenSocket_UDP_get == INVALID_SOCKET) {
logger->error("创建套接字失败:" + WSAGetLastError());
std::cout << "创建套接字失败:"<< WSAGetLastError() << std::endl;
WSACleanup();
exit(0);
}
//填充服务端信息
service_UDP_get.sin_family = AF_INET; // 设置地址族为 IPv4
service_UDP_get.sin_addr.s_addr = INADDR_ANY; // 将 IP 地址设置为 0.0.0.0,表示绑定到所有本地 IP 地址
service_UDP_get.sin_port = htons(port); // 将端口号转换为网络字节序,并设置为指定的端口号
// 绑定套接字
if (bind(ListenSocket_UDP_get, (SOCKADDR*)&service_UDP_get, sizeof(service_UDP_get)) == SOCKET_ERROR)
{
logger->error("绑定套接字失败: " + WSAGetLastError());
std::cout << "绑定套接字失败: " + WSAGetLastError() << std::endl;
closesocket(ListenSocket_UDP_get);
WSACleanup();
exit(0);
}
char recvbuf[512]; // 定义接收信息的缓冲区,大小为512字节
int iRecvResult; // 存储接收操作的返回结果
sockaddr_in clientAddr; // 用于存储客户端的地址信息
int iAddrLen = sizeof(clientAddr); // 存储地址结构体的大小
do
{
std::cout << "服务端正在等待数据发送,请稍候...." << std::endl;
// 接收来自客户端的数据
iRecvResult = recvfrom(ListenSocket_UDP_get, recvbuf, sizeof(recvbuf), 0, (SOCKADDR*)&clientAddr, &iAddrLen);
// std::cout << iRecvResult << std::endl;
// 检查接收操作是否成功
if (iRecvResult > 0)
{
std::string result(recvbuf, iRecvResult);
std::cout << "收到信息:" + result << std::endl;
logger->info("收到信息:" + result);
// 将接收到的数据发送回客户端
// sendto(ListenSocket_UDP, recvbuf, iRecvResult, 0, (SOCKADDR*)&clientAddr, sizeof(clientAddr));
}
else if (iRecvResult == 0)
{
std::cout << "连接关闭" << std::endl;
logger->info("连接关闭");
}
else
{
std::cout << "接受信息失败:" << WSAGetLastError() << std::endl;
logger->error("接受信息失败:" + WSAGetLastError());
closesocket(ListenSocket_UDP_get);
WSACleanup();
}
} while (iRecvResult > 0);
closesocket(ListenSocket_UDP_get);
WSACleanup();
}
void SocketManager::initialization() {
//初始化套接字库
WORD w_req = MAKEWORD(2, 2);//版本号
WSADATA wsadata;
int err;
err = WSAStartup(w_req, &wsadata);
if (err != 0) {
std::cout << "初始化套接字库失败!" << std::endl;
}
//检测版本号
if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2) {
std::cout << "套接字库版本号不符!" << std::endl;
WSACleanup();
}
//填充服务端地址信息
}
void SocketManager::send_to_tcp(std::string str, std::string ip, int port) {
int send_len = 0;
// 初始化套接字库
initialization();
//填充服务端信息
service_TCP_to.sin_family = AF_INET;
service_TCP_to.sin_addr.S_un.S_addr = inet_addr(ip.c_str());
service_TCP_to.sin_port = htons(port);
//创建套接字
SendSocket_TCP_to = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (SendSocket_TCP_to == INVALID_SOCKET) {
logger->error("创建套接字失败:" + WSAGetLastError());
std::cout << "创建套接字失败:" << WSAGetLastError() << std::endl;
WSACleanup();
exit(1);
}
if (connect(SendSocket_TCP_to, (SOCKADDR*)&service_TCP_to, sizeof(SOCKADDR)) == SOCKET_ERROR) {
std::cout << "服务器连接失败:" << WSAGetLastError() << std::endl;
logger->error("服务器连接失败:" + WSAGetLastError());
WSACleanup();
exit(1);
}
// 发送信息
send_len = send(SendSocket_TCP_to, str.c_str(), str.size(), 0);
if (send_len < 0) {
std::cout << "发送失败:" << WSAGetLastError() << std::endl;
logger->error("发送失败:" + WSAGetLastError());
}
std::cout << send_len << "发送成功" << std::endl;
//关闭套接字
//closesocket(SendSocket_TCP_to);
//释放DLL资源
//WSACleanup();
}
void SocketManager::get_from_tcp(int port) {
// 初始化套接字库
initialization();
// 创建套接字
ListenSocket_TCP_get = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // tcp与udp之间有所不同
if (ListenSocket_TCP_get == INVALID_SOCKET) {
logger->error("创建套接字失败:" + WSAGetLastError());
std::cout << "创建套接字失败:" << WSAGetLastError() << std::endl;
WSACleanup();
exit(1);
}
//填充服务端信息
service_TCP_get.sin_family = AF_INET; // 设置地址族为 IPv4
service_TCP_get.sin_addr.s_addr = INADDR_ANY; // 将 IP 地址设置为 0.0.0.0,表示绑定到所有本地 IP 地址
service_TCP_get.sin_port = htons(port); // 将端口号转换为网络字节序,并设置为指定的端口号
// 绑定套接字
if (bind(ListenSocket_TCP_get, (SOCKADDR*)&service_TCP_get, sizeof(service_TCP_get)) == SOCKET_ERROR)
{
logger->error("绑定套接字失败: " + WSAGetLastError());
std::cout << "绑定套接字失败: " + WSAGetLastError() << std::endl;
closesocket(ListenSocket_TCP_get);
WSACleanup();
exit(1);
}
char recvbuf[512]; // 定义接收信息的缓冲区,大小为512字节
int iRecvResult; // 存储接收操作的返回结果
int len = 0;
//设置套接字为监听状态
if (listen(ListenSocket_TCP_get, SOMAXCONN) < 0) {
std::cout << "设置监听状态失败:" << WSAGetLastError() << std::endl;
logger->error("设置监听状态失败:" + WSAGetLastError());
WSACleanup();
}
std::cout << "服务端正在监听连接,请稍候...." << std::endl;
len = sizeof(service_TCP_get);
SOCKET ClientSocket = INVALID_SOCKET; // 初始化 ClientSocket 变量并将其设置为无效的套接字
do
{
std::cout << "服务端正在等待数据发送,请稍候...." << std::endl;
ClientSocket = accept(ListenSocket_TCP_get, (SOCKADDR*)&service_TCP_get, &len); // 等待客户端连接请求并接受连接
/*
accept 函数会阻塞,直到有客户端连接请求到达,然后返回一个新的套接字
ListenSocket_TCP_get 是服务器监听的套接字
service_TCP_get 是用于存储客户端地址信息的结构体
len 是地址结构体的大小,accept 函数调用时会被更新为实际的地址大小
*/
// std::cout << ClientSocket << std::endl;
if (ClientSocket == SOCKET_ERROR) {
std::cout << "算法端连接失败:" + WSAGetLastError() << std::endl;
logger->error("算法端连接失败:" + WSAGetLastError());
WSACleanup();
exit(2);
}
// 接收来自客户端的数据
iRecvResult = recv(ClientSocket, recvbuf, sizeof(recvbuf), 0);
// 检查接收操作是否成功
if (iRecvResult > 0)
{
// std::cout << iRecvResult << std::endl;
std::string result(recvbuf, iRecvResult);
std::cout << "收到信息:" + result << std::endl;
logger->info("收到信息:" + result);
// 将接收到的数据发送回客户端
// sendto(ListenSocket_UDP, recvbuf, iRecvResult, 0, (SOCKADDR*)&clientAddr, sizeof(clientAddr));
}
else if (iRecvResult == 0)
{
std::cout << "连接关闭" << std::endl;
logger->info("连接关闭");
}
else
{
std::cout << "接受信息失败:" << WSAGetLastError() << std::endl;
logger->error("接受信息失败:" + WSAGetLastError());
closesocket(ListenSocket_UDP_get);
WSACleanup();
}
} while (iRecvResult > 0);
closesocket(ListenSocket_TCP_get);
WSACleanup();
}
void SocketManager::send_to_udp(std::string str, std::string ip, int port) {
int send_len = 0;
// 初始化套接字库
initialization();
//填充服务端信息
service_UDP_to.sin_family = AF_INET;
service_UDP_to.sin_addr.S_un.S_addr = inet_addr(ip.c_str());
service_UDP_to.sin_port = htons(port);
//创建套接字
SendSocket_UDP_to = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (SendSocket_UDP_to == INVALID_SOCKET) {
logger->error("创建套接字失败:" + WSAGetLastError());
std::cout << "创建套接字失败:" << WSAGetLastError() << std::endl;
WSACleanup();
exit(0);
}
int iSendResult = sendto(SendSocket_UDP_to, str.c_str(), str.size(), 0, (SOCKADDR*)&service_UDP_to, sizeof(service_UDP_to));
if (iSendResult == SOCKET_ERROR) {
std::cout << "发送失败:" << WSAGetLastError() << std::endl;
logger->error("发送失败:" + WSAGetLastError());
}
//关闭套接字
closesocket(SendSocket_UDP_to);
//释放DLL资源
WSACleanup();
}
std::string asciiToHex(const std::string& asciiStr) {
std::string hexStr;
for (char c : asciiStr) {
unsigned char value = static_cast<unsigned char>(c);
hexStr += std::to_string(static_cast<int>(value >> 4)) + std::to_string(static_cast<int>(value & 0x0F));
}
return hexStr;
}