当前位置: 首页 > news >正文

以udp协议创建通信服务器

概念图

 创建服务器让A,B主机完成通信。

认识接口

socket

 返回值:套接字,你可以认为类似fd

参数:

  1. domain->:哪种套接字,常用AF_INET(网络套接字)、AF_LOCAL(本地套接字)
  2. type->:发送数据类型,常用 SOCK_DGRAM(以数据报式发送)
  3. protocol->:一般填0,自动推导类型或者IPPROTO_UDP、IPPROTO_TCP。

创建一个套接字,类似创建一个文件标识符fd。

先介绍些结构体类型

struct sockaddr
struct sockaddr_in
struct sockaddr_un

_in结构体中保存的是ip\port数据,而_un中保存的则是本地的数据

udp协议为了本地通信与网络通信同一套接口兼容,所以先将sockaddr_in/_un强转成sockaddr类型传入各个函数,在函数中判断前2个字节类型,来做本地通信或者网络通信。

bind

将套接字绑定,一般来说套接字绑定都是服务器才会绑定的,客户端一般给操作系统自动分配ip与端口的。

返回值:成功0,失败-1.设置错误码

参数:

  1. sockfd 需要绑定的套接字
  2. sockaddr包含了需要与套接字绑定的ip和端口号。
  3. addrlen该结构体长度。

recvfrom

用来接收数据的接收

返回值:实际接收数据的长度,-1失败

参数

  1. sockfd:将从该套接字的端口和ip中取得数据
  2. buff:输出型参数,将数据存放到buff中。
  3. len:buff的长度
  4. flags:以状态等待数据,一般填0,阻塞等待数据
  5. src_addr:发送方ip+port结构体数据,输出型参数
  6. 结构体数据长度

sendto

发送数据给某个主机

返回值:实际发送数据的个数,-1失败

参数

  1. sockfd:将发送方的ip+port发送给对方
  2. buff:输入型参数,将buff中数据发送给对方。
  3. len:buff的长度;
  4. flags:默认发送方式发送
  5. 接收方ip+port结构体数据,根据该参数寻找对于主机
  6. 结构体数据长度

sockaddr_in结构体配套函数

机器大小端的转换函数。h本地to转

以太网规定,网络传输数据一定是大端方式传输,所以我们的机器无论是大端还是小端,在网络中都会成为大端序列。

 当是为了人能看的明白,我们的ip地址一般都是以字符串的方式呈现,这样的方式我们称为点分十进制的方式。而且传入为了的ip地址可能需要改序列,所以一批接口出现了。

这些接口将字符串转为uint32_t或者将uint32_t转为字符串

代码

一份2个主机通过服务器可以聊天的代码

服务器代码:

server.hpp

#pragma once
#include <cstdio>
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "Log.hpp"
#include <unordered_map>
using std::cin;
using std::cout;
using std::endl;class udp_server
{typedef int socket_t;void ip_type(){cout << "ip:" << _ip << endl;if (_ip == "127.0.0.1"){cout << "#####本地测试#####" << endl;}else if (_ip.empty()){cout << "#####开放全部ip地址#####" << endl;}else{cout << "#####指定ip地址#####" << endl;}}void init_server(){_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);if (_socket < 0){Log(FATAL, "socket get fail!!![%d][%s]\n", __LINE__, __TIME__);exit(1);}struct sockaddr_in ip_port;bzero(&ip_port, sizeof(ip_port));ip_port.sin_family = AF_INET;ip_port.sin_addr.s_addr = _ip.empty() ? INADDR_ANY : inet_addr(_ip.c_str());ip_port.sin_port = htons(_port);if (bind(_socket, (struct sockaddr *)&ip_port, sizeof(ip_port)) < 0){Log(FATAL, "bind  fail!!![%d][%s]\n", __LINE__, __TIME__);exit(2);}Log(NORMAL, "udp init success!!![%d][%s]\n", __LINE__, __TIME__);}public:udp_server(uint16_t port, std::string ip = "") : _ip(ip), _port(port) {}udp_server() {}void activate(){init_server();ip_type();while (1){char buff[1024] = {0};// cout<<"buff size: "<<strlen(buff)<<endl;struct sockaddr_in client_ip_port;socklen_t len = sizeof(client_ip_port);//开始等待客户端ssize_t end = recvfrom(_socket, buff, sizeof(buff) - 1, 0, (struct sockaddr *)&client_ip_port, &len);char retbuff[1024]={0};// cout<<"buff size: "<<strlen(buff)<<endl;if (end >= 0){buff[end] = '\0';printf("[%s:%d]clint say# %s\n", inet_ntoa(client_ip_port.sin_addr), ntohs(client_ip_port.sin_port), buff);sprintf(retbuff,"[%s:%d]clint say# %s", inet_ntoa(client_ip_port.sin_addr), ntohs(client_ip_port.sin_port), buff);}else{Log(WARINNG, "recvfrom Message have fail [%d][%s]\n", __LINE__, __TIME__);}//处理数据。char key[64];snprintf(key,sizeof(key),"%s-%u",inet_ntoa(client_ip_port.sin_addr),client_ip_port.sin_port);auto it = _users.find(key);if(it==_users.end()){cout<<key<<endl;cout<<key<<" :放入客户端"<<endl;_users.insert({key,client_ip_port});}// cout<<"end : "<<end<<endl;//反馈for(auto&it:_users){if(client_ip_port.sin_addr.s_addr==it.second.sin_addr.s_addr){continue;}sendto(_socket, retbuff, sizeof retbuff, 0, (struct sockaddr *)&(it.second), sizeof(it.second));}Log(Debug, "sendto Message have fail [%d][%s]\n", __LINE__, __TIME__);}}private:socket_t _socket;std::string _ip;uint16_t _port;std::unordered_map<std::string, struct sockaddr_in> _users;
};

server.cpp

#include "server.hpp"
#include <memory>
using std::shared_ptr;
void SERVERUER()
{std::cout<<"./server + ip + port"<<std::endl;
}int main(int argc,char*argv[])
{if(argc==2||argc==3){cout<<"argc:"<<argc<<endl;if(argc==2){in_port_t port=atoi(argv[1]);shared_ptr<udp_server> server_ptr(new udp_server(port));server_ptr->activate();}else{in_port_t port=atoi(argv[2]);std::string ip=argv[1];shared_ptr<udp_server> server_ptr(new udp_server(port,ip));server_ptr->activate();}}else{SERVERUER();}return 0;
}

客户端代码

client.cpp

#include <cstdio>
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "Log.hpp"
#include <pthread.h>
using std::cin;
using std::cout;
using std::endl;
typedef int socket_t;void CLIENTUER()
{std::cout << "./client + ip + port" << std::endl;
}void *thread_func(void *ages)
{socket_t *_socket = (socket_t*)ages;char get_messages[102];struct sockaddr_in temp;bzero((void *)&temp, sizeof(temp));socklen_t len(sizeof temp);while (1){ssize_t end = recvfrom(*_socket, get_messages, sizeof(get_messages) - 1, 0, (struct sockaddr *)&temp, &len);if (end >= 0){get_messages[end] = 0;std::cout<< get_messages << std::endl;}}return nullptr;
}int main(int argc, char *argv[])
{if (argc != 3){CLIENTUER();exit(1);}socket_t _socket = socket(AF_INET, SOCK_DGRAM, 0);pthread_t tid;pthread_create(&tid,nullptr,thread_func,(void*)&_socket);std::string messages;struct sockaddr_in server_ip_port;bzero(&server_ip_port, sizeof(server_ip_port));server_ip_port.sin_family = AF_INET;server_ip_port.sin_addr.s_addr = inet_addr(argv[1]);server_ip_port.sin_port = htons(atoi(argv[2]));socklen_t len = sizeof(server_ip_port);while (1){fflush(stdout);std::getline(std::cin, messages);sendto(_socket, messages.c_str(), messages.size(), 0, (struct sockaddr *)&server_ip_port, len);}return 0;
}

相关文章:

以udp协议创建通信服务器

概念图 创建服务器让A,B主机完成通信。 认识接口 socket 返回值&#xff1a;套接字&#xff0c;你可以认为类似fd 参数&#xff1a; domain->:哪种套接字&#xff0c;常用AF_INET(网络套接字)、AF_LOCAL(本地套接字)type->&#xff1a;发送数据类型&#xff0c;常用 …...

【数据结构】队列篇| 超清晰图解和详解:循环队列模拟、用栈实现队列、用队列实现栈

博主简介&#xff1a;努力学习的22级计算机科学与技术本科生一枚&#x1f338;博主主页&#xff1a; 是瑶瑶子啦每日一言&#x1f33c;: 每一个不曾起舞的日子&#xff0c;都是对生命的辜负。——尼采 目录 一、 模拟实现循环队列二、用栈实现队列⭐三、225. 用队列实现栈 一、…...

js+html实现打字游戏v2

实现逻辑&#xff0c;看jshtml实现打字游戏v1&#xff0c;在此基础之上增加了从文件读取到的单词&#xff0c;随机选取10个单词。 效果演示 上代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8">&l…...

Python之作业(一)

Python之作业&#xff08;一&#xff09; 作业 打印九九乘法表 用户登录验证 用户依次输入用户名和密码&#xff0c;然后提交验证用户不存在、密码错误&#xff0c;都显示用户名或密码错误提示错误3次&#xff0c;则退出程序验证成功则显示登录信息 九九乘法表 代码分析 先…...

uni-app 之 v-on:click点击事件

uni-app 之 v-on:click点击事件 image.png <template><!-- vue2的<template>里必须要有一个盒子&#xff0c;不能有两个&#xff0c;这里的盒子就是 view--><view>--- v-on:click点击事件 ---<view v-on:click"onclick">{{title}}<…...

迁移学习:实现快速训练和泛化的新方法

文章目录 迁移学习的原理迁移学习的应用快速训练泛化能力提升 迁移学习的代码示例拓展应用与挑战结论 &#x1f389;欢迎来到AIGC人工智能专栏~迁移学习&#xff1a;实现快速训练和泛化的新方法 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#xff1a;IT陈寒的博…...

蓝队追踪者工具TrackAttacker,以及免杀马生成工具

蓝队追踪者工具TrackAttacker&#xff0c;以及免杀马生成工具。 做过防守的都知道大HW时的攻击IP量&#xff0c;那么对于这些攻击IP若一个个去溯源则显得效率低下&#xff0c;如果有个工具可以对这些IP做批量初筛是不是更好&#xff1f; 0x2 TrackAttacker获取 https://githu…...

ELK日志收集系统(四十九)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、概述 二、组件 1. elasticsearch 2. logstash 2.1 工作过程 2.2 INPUT 2.3 FILETER 2.4 OUTPUTS 3. kibana 三、架构类型 3.1 ELK 3.2 ELKK 3.3 ELFK 3.5 EF…...

Linux知识点 -- Linux多线程(四)

Linux知识点 – Linux多线程&#xff08;四&#xff09; 文章目录 Linux知识点 -- Linux多线程&#xff08;四&#xff09;一、线程池1.概念2.实现3.单例模式的线程池 二、STL、智能指针和线程安全1.STL的容器是否是线程安全的2.智能指针是否是线程安全的 三、其他常见的各种锁…...

Java设计模式:四、行为型模式-07:状态模式

文章目录 一、定义&#xff1a;状态模式二、模拟场景&#xff1a;状态模式2.1 状态模式2.2 引入依赖2.3 工程结构2.4 模拟审核状态流转2.4.1 活动状态枚举2.4.2 活动信息类2.4.3 活动服务接口2.4.4 返回结果类 三、违背方案&#xff1a;状态模式3.0 引入依赖3.1 工程结构3.2 活…...

很多应用都是nginx+apache+tomcat

nginx 负责负载均衡&#xff0c;将大量的访问量平衡分配给多个服务器 apache 是用来处理静态html、图片等资源&#xff0c;在对HTML解析、响应等方面比tomcat效率更高。 tomcat 处理JSP等内容&#xff0c;进行后台业务操作。 upstream bbb.com.cn{ server 192.168.10.1:80 ;…...

原型模式:复制对象的技巧

欢迎来到设计模式系列的第六篇文章&#xff01;在前面的几篇文章中&#xff0c;我们已经学习了一些常见的设计模式&#xff0c;今天我们将继续探讨另一个重要的设计模式——原型模式。 原型模式简介 原型模式是一种创建型设计模式&#xff0c;它主要用于复制对象。原型模式通…...

ClickHouse进阶(五):副本与分片-1-副本与分片

进入正文前&#xff0c;感谢宝子们订阅专题、点赞、评论、收藏&#xff01;关注IT贫道&#xff0c;获取高质量博客内容&#xff01; &#x1f3e1;个人主页&#xff1a;含各种IT体系技术,IT贫道_Apache Doris,大数据OLAP体系技术栈,Kerberos安全认证-CSDN博客 &#x1f4cc;订阅…...

Android 华为手机荣耀8X调用系统裁剪工具不能裁剪方形图片,裁剪后程序就奔溃,裁剪后获取不到bitmap的问题

买了个华为荣耀8X,安装自己写的App后,调用系统裁剪工具发现裁剪是圆形的,解决办法: //专门针对华为手机解决华为手机裁剪图片是圆形图片的问题 if (Build.MANUFACTURER.equals("HUAWEI")) {intent.putExtra("aspectX", 9998);intent.putExtra("a…...

《Flink学习笔记》——第十二章 Flink CEP

12.1 基本概念 12.1.1 CEP是什么 1.什么是CEP&#xff1f; 答&#xff1a;所谓 CEP&#xff0c;其实就是“复杂事件处理&#xff08;Complex Event Processing&#xff09;”的缩写&#xff1b;而 Flink CEP&#xff0c;就是 Flink 实现的一个用于复杂事件处理的库&#xff08…...

谷歌IndexedDB客户端存储数据

IndexedDB 具有以下主要特点&#xff1a; 1.存储大量数据&#xff1a;IndexedDB 可以存储大量的数据&#xff0c;比如存储离线应用程序的本地缓存或存储在线应用程序的大量数据。 2.结构化数据&#xff1a;IndexedDB 使用对象存储空间&#xff08;Object Stores&#xff09;来…...

天气数据的宝库:解锁天气预报API的无限可能性

前言 天气预报一直是我们日常生活中的重要组成部分。我们依赖天气预报来决定穿什么衣服、何时出行、规划户外活动以及做出关于农业、交通和能源管理等方面的重要决策。然而&#xff0c;要提供准确的天气预报&#xff0c;需要庞大的数据集和复杂的计算模型。这就是天气预报API的…...

插入排序(Insertion Sort)

C自学精简教程 目录(必读) 插入排序 每次选择未排序子数组中的第一个元素&#xff0c;从后往前&#xff0c;插入放到已排序子数组中&#xff0c;保持子数组有序。 打扑克牌&#xff0c;起牌。 输入数据 42 20 17 13 28 14 23 15 执行过程 完整代码 #include <iostream…...

2023蓝帽杯初赛

最近打完蓝帽杯 现在进行复盘 re 签到题 直接查看源代码 输出的内容就是 变量s 变量 number 而这都是已经设定好了的 所以flag就出来了 WhatisYourStory34982733 取证 案件介绍 取证案情介绍&#xff1a; 2021年5月&#xff0c;公安机关侦破了一起投资理财诈骗类案件&a…...

风险评估

风险评估概念 风险评估是一种系统性的方法&#xff0c;用于识别、评估和量化潜在的风险和威胁&#xff0c;以便组织或个人能够采取适当的措施来管理和减轻这些风险。 风险评估的目的 风险评估要素关系 技术评估和管理评估 风险评估分析原理 风险评估服务 风险评估实施流程...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

SpringCloudGateway 自定义局部过滤器

场景&#xff1a; 将所有请求转化为同一路径请求&#xff08;方便穿网配置&#xff09;在请求头内标识原来路径&#xff0c;然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中&#xff0c;新增了一个本地验证码接口 /code&#xff0c;使用函数式路由&#xff08;RouterFunction&#xff09;和 Hutool 的 Circle…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

AI语音助手的Python实现

引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...

LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)

在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...