socket 收发TCP/UDP

news2024/12/24 22:09:55

一、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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1937082.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PE安装系统

前些天客户的电脑坏了,需要重装系统,我们的恢复光盘安装的时候,由于主板的原因,导致进入windows安装界面,鼠标键盘没有响应,自然也就无法正常安装了. 那我们只能换个方法,PE安装试试看,那么我们需要做哪些准备工作呢? 1.制作PE启动盘,网上很多制作工具,如""U启动,…

贪心算法总结(1)

一、贪心算法简介 常用方法&#xff1a;交换论证法、数学归纳法、反证法、分类讨论 二、柠檬水找零&#xff08;交换论证法&#xff09; . - 力扣&#xff08;LeetCode&#xff09; class Solution { public:bool lemonadeChange(vector<int>& bills) {int five0,t…

蜂窝物联云平台:一站式服务,智能生活从此开始!

蜂窝云平台 一、PC端展示与管理 GIS地图整合 在GIS地图上精确展示地块&#xff0c;轻松点选查看详细设备信息、实时监控和控制功能&#xff0c;以及基地的全方位介绍。 个性化定制界面 界面布局与功能展示均可按需求定制&#xff0c;打造独一无二的用户体验。 数据集中看板 将…

html网页使用tesseract实现OCR文字识别

即在前端实现OCR文字识别 1.前端代码 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>OCR文字识别…

C/C++ json库

文章目录 一、介绍1.1 json 介绍 二、C/C json 库选型2.1 选型范围2.2 jsoncpp2.2.2 jsoncpp 编译和交叉编译 2.3 rapidjson2.4 nlohmann/json2.5 sonic-cpp 五、常见问题5.1 jsoncpp 中关于浮点数的控制和中文显示问题5.2 jsoncpp序列化double类型时精度损失问题的解决办法 一…

JavaWeb JavaScript ① JS简介

目录 一、HTML&CSS&JavaScript的作用 二、前后端关联标签——表单标签 1.form标签 2.input标签 3.get/post提交的差异 4.表单项标签 5.布局相关标签 块元素——div 行内元素——span 三、CSS 1.CSS引入方式 方式1 行内式 方式2 内嵌式 方式3 外部样式表 2.CSS选择器 元…

AWS Certified Developer Associate备考笔记

AWS Certified Developer Associate备考笔记 缓慢更新中&#xff0c;如果你也正在关注该考试&#xff0c;请点赞后评论感兴趣的章节&#xff0c;可加快我的更新速度 &#x1f603; 文章目录 AWS Certified Developer Associate备考笔记一、IAM二、EC2三、EC2 Instance Storage…

Spring Boot项目中使用MyBatis Generator (MBG) 自动生成Mapper文件

Spring Boot项目中使用MyBatis Generator (MBG) 自动生成Mapper文件可以很大程度上减少编码。本文着重介绍如何在实战中使用MGB自动生成Mapper文件 1. 添加MyBatis Generator依赖 在pom.xml中添加必要的依赖 <dependency><groupId>org.mybatis.spring.boot</…

【Python系列】Python 中的文件读取

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

秒懂设计模式--学习笔记(11)【结构型-享元模式】

目录 10、享元模式10.1 享元模式10.2 举例10.2.1 马赛克10.2.2 游戏地图&#xff08;以草原地图作为范例&#xff09; 10.3 总结 10、享元模式 10.1 享元模式 “享元”则是共享元件的意思享元模式的英文flyweight是轻量级的意思&#xff0c;这就意味着享元模式能使程序变得更…

Training for Stable Diffusion

Training for Stable Diffusion 笔记来源&#xff1a; 1.Denoising Diffusion Probabilistic Models 2.最大似然估计(Maximum likelihood estimation) 3.Understanding Maximum Likelihood Estimation 4.How to Solve ‘CUDA out of memory’ in PyTorch 1.1 Introduction 训…

FastBee物联网开源项目本地启动调试

一、本地环境准备 &#xff08;1&#xff09;Visual Studio Code&#xff08;启动前端项目&#xff09; &#xff08;2&#xff09;IntelliJ IDEA Community Edition &#xff08;启动后端项目&#xff09; &#xff08;3&#xff09;Navicat或者DBeaver&#xff08;用来操…

Godot学习笔记2——GDScript变量与函数

目录 一、代码编写界面 二、变量 三、函数 四、变量的类型 Godot使用的编程语言是GDS&#xff0c;语法上与python有些类似。 一、代码编写界面 在新建的Godot项目中&#xff0c;点击“创建根节点”中的“其他节点”&#xff0c;选择“Node”。 点击场景界面右上角的绿色…

【STM32】按键控制LED光敏传感器控制蜂鸣器(江科大)

一、按键控制LED LED.c #include "stm32f10x.h" // Device header/*** 函 数&#xff1a;LED初始化* 参 数&#xff1a;无* 返 回 值&#xff1a;无*/ void LED_Init(void) {/*开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENAB…

此扩展在此工作区中被禁用,因为其被定义为在远程扩展主机中运行。

使用VScode打开代码时&#xff0c;无法跳转函数&#xff0c;不提示报错。 安装python时显示&#xff0c; 此扩展在此工作区中被禁用&#xff0c;因为其被定义为在远程扩展主机中运行。 解决方法&#xff1a; CtrlShiftP &#xff1a;键入trust &#xff0c;工作区&#xff…

空间计算新时代:Vision Pro引领AR/VR/MR市场变革

随着2024年第二季度的结束&#xff0c;空间计算领域的市场动态愈发引人关注。根据国际数据公司&#xff08;IDC&#xff09;的最新报告&#xff0c;我们见证了行业格局的重大变化&#xff0c;尤其是苹果Vision Pro的突出表现&#xff0c;以及AR/VR/MR设备市场的整体趋势。以下是…

LabVIEW软件开发的雷区在哪里?

在LabVIEW软件开发中&#xff0c;有几个需要注意的雷区&#xff0c;以避免常见的错误和提高开发效率&#xff1a; 1. 不良的代码结构 雷区&#xff1a;混乱的代码结构和不清晰的程序逻辑。 后果&#xff1a;导致难以维护和调试的代码&#xff0c;增加了错误和故障的风险。 …

无人机侦察:二维机扫雷达探测设备技术详解

二维机扫雷达探测设备采用机械扫描方式&#xff0c;通过天线在水平方向和垂直方向上的转动&#xff0c;实现对目标空域的全方位扫描。雷达发射机发射电磁波信号&#xff0c;遇到目标后产生反射&#xff0c;反射信号被雷达接收机接收并处理&#xff0c;进而得到目标的位置、速度…

搜维尔科技:【研究】动作捕捉加速游戏开发行业的发展

动作捕捉加速游戏开发行业的发展 Sunjata 的故事始于 2004 年&#xff0c;它将席卷乌干达视频游戏行业&#xff0c;然后席卷全世界。但首先&#xff0c;Klan Of The Kings 的小团队需要工具来实现他们的愿景。 漫画家兼非洲民间传说爱好者罗纳德卡伊马 (Ronald Kayima) 在将…

怎样在 PostgreSQL 中进行用户权限的精细管理?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01;&#x1f4da;领书&#xff1a;PostgreSQL 入门到精通.pdf 文章目录 怎样在 PostgreSQL 中进行用户权限的精细管理&#xff1f;一、权限管理的重要性二、PostgreSQL 中的权…