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

UDP协议讲解

预备知识:

端口号port:

我们在正常网络通信时,实际上是进程在互相通信。

我们所有的网络通信的行为,本质上都是进程间通信。

对双方而言,1.先保证数据能到达自己的机器 ip解决 2.找到指定的进程 端口号

ip地址用来标识互联网中唯一一台主机

端口号用来表示该指定的主机的进程的唯一性

所以ip+port={ip,port}互联网中唯一一个进程

{ip,port}我们把它叫做套接字,socket

如何理解端口号?uint16_t port

16位的数字,uint16_t port,用来标识主机的唯一的一个网络进程

为什么不直接用pid来表示网络中唯一一个进程

1.进程管理和网络管理进行解耦

2.port用来专门为网络通信

一个端口和一个进程进行关联?

一个进程可以和多个端口号关联,但是多个进程不能和一个端口号关联。

ip也可以对应多个端口号。

TCP和UDP

TCP协议:面向链接,面向字节流,可靠通信

UDP协议:面向数据报,无连接,不可靠通信

既然有了可靠通信,为什么又要设计不可靠通信

中性词,可靠通信,要得到保证就必须做更多的工作(复杂),不可靠通信,做更少的工作,很简单,丢包率也不会太高。他们之间只有不同没有好坏。

网络字节序列

在存储上我们有大端存储(大权值在低地址)和小端存储

也就是说不同机器的存储方式是不同的

我们在发数据,在内存中是以低地址到高地址发送,接收主机在内存中读取也是从低地址到高地址接收

网络规定达到网络的数据,都以大端发送,所有机器都知道数据是以大端发送的,所以小端机器就大端转化

到小端。因为主机的大小端是不一样的。

htonl:host to net int

因为port需要通过网络递送,所以得转成网络序列

socket:网路编程,socket是有很多类别的

1.unix socket :域间socket;同一台主机 的文件路径,在本主机进行通信

2.网络socket:ip+port:网络通信的文件

3.原始socket:编写一些网络工具

理论上以上三种类别都要有自己的一套接口

但是设计者只想用一套接口是一套通用的地址类型

Server服务器

创建套接字

return value;返回一个文件描述符

domain:网络通信的协议家族,也叫域

type:套接字的类型

protocol:tcp 或 udp

struct sockaddr_in local;

bzero(&lock,sizeof(local))

local.sin_family=AF_INET

local.sin_port=htons(_port)

local.sin_addr.s_addr=inet_addr(_ip)

​完成下列功能

1.四字节ip 2.网络序列

创建了socket我们要把他绑定,将它与socket关联

sockfd:socket返回的文件描述符

addr:传入sockaddr_un 或者 sockaddr_in

addrlen:结构体长度

服务器永远不退出,在Start中注定是一个死循环、

服务器接收

返回的是实际字节,len的期望收到的字节,flags默认为0(阻塞收消息)

后两个参数为输入输出型参数:给我们客户端client的信息 ip port,以后发消息就发给这个客户端

服务器发送

#pragma once
#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <unistd.h>#include <sys/types.h>
#include <sys/socket.h>#include <netinet/in.h>
#include <arpa/inet.h>#include "nocopy.hpp"
#include "Log.hpp"
#include "Comm.hpp"using namespace std;
const uint16_t defaultport = 8888;
const int defaultsocketfd = -1;
const int buffsize = 1024;class Udpserver : public nocopy
{
public:Udpserver(const uint16_t port = defaultport): _port(port), _socketfd(defaultsocketfd){}void Init(){// socket_socketfd = socket(AF_INET, SOCK_DGRAM, 0);if (_socketfd < 0){lg.LogMessage(Fatal, "socket errr, %d : %s\n", errno, strerror(errno));cout << endl;exit(socketfderror);}lg.LogMessage(Info, "socketfd success \n");cout << endl;struct sockaddr_in local;bzero(&local, sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(_port);local.sin_addr.s_addr = INADDR_ANY;// bindint n = ::bind(_socketfd, (struct sockaddr *)&local, sizeof(local));if (n < 0){lg.LogMessage(Fatal, "bind error,%d : %s\n", errno, strerror(errno));cout << endl;exit(binderror);}lg.LogMessage(Info, "bind success\n");cout << endl;}void Start(){for (;;){struct sockaddr_in peer;socklen_t peerlen = sizeof(peer);char rbuff[1024];ssize_t n = recvfrom(_socketfd, rbuff, sizeof(rbuff - 1), 0, (struct sockaddr *)&peer, &peerlen);rbuff[n] = '\0';cout << "recv info:" << rbuff << endl;// if (n < 0)// {//   lg.LogMessage(Fatal, "recvfrom error,%d : %s\n", errno, strerror(errno));// }// rbuff[n]='\0';ssize_t sendn = sendto(_socketfd, rbuff, sizeof(buffsize), 0, (struct sockaddr *)&peer, peerlen);cout << "sendn success:" << rbuff << endl;if (n < 0){lg.LogMessage(Fatal, "sendto error,%d : %s\n", errno, strerror(errno));}}}~Udpserver() {}private:// string _ip;uint16_t _port;int _socketfd;
};

netstat: 查看网络连接 -anup

Client客户端

创建套接字

client需不需要绑定,一定需要,但不需要显示绑定,client向服务器第一次发送信息时会自动绑定

为什么?

server的port众所周知是不可以随意改变的,client的port是随机端口,这是由于启动客户端的进程是很多

​的,

127.0.0.1:本地循环,通常用来网络cs的测试

我们想看到客户端的信息应该如何看到?

绑定云服务器地址失败?

云服务器的公网ip是虚拟的,无法直接bind,不推荐,更推荐本地任意ip的绑定方式

如何进行服务端的任意本地ip的绑定

IP=INADDR_ANY 实现动态绑定 0.0.0.0表示任意绑定

#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <unistd.h>#include <sys/types.h>
#include <sys/socket.h>#include <netinet/in.h>
#include <arpa/inet.h>
#include "Log.hpp"
#include "Comm.hpp"
const int defaultsrecbuff = 1024;
using namespace std;
void Usage(char *argv)
{cout << "Usage:" << argv << "+ServerIp+ServerPort" << endl;
}
int main(int argc, char *argv[])
{if (argc < 3){Usage(argv[0]);cerr << "use client error" << endl;return Usage_Err;}// 创建套接字int socketfd = socket(AF_INET, SOCK_DGRAM, 0);// 填充server 发送信息string serverip = argv[1];uint16_t serverport = stoi(argv[2]);struct sockaddr_in server;bzero(&server, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(serverport);server.sin_addr.s_addr = inet_addr(serverip.c_str());while (true){string buff;cout << "#Please enter:";getline(cin, buff);int n = sendto(socketfd, buff.c_str(), buff.size(), 0,(const struct sockaddr *)&server, sizeof(server));if (n < 0){cerr << "send error" << errno << strerror(errno);break;}else{// 接收信息struct sockaddr_in peer;socklen_t peerlen = sizeof(peer);char recbuff[defaultsrecbuff];int m = recvfrom(socketfd, recbuff, sizeof(recbuff)-1, 0,(struct sockaddr *)&peer, &peerlen);if (m < 0){cerr << "rec error" << errno << strerror(errno);break;}else{recbuff[m]=0;cout << "#server say:" << recbuff << endl;}}}close(socketfd);
}

​​

http://www.lryc.cn/news/464016.html

相关文章:

  • 交叉注意力融合时域、频域特征的FFT + CNN -BiLSTM-CrossAttention轴承故障识别模型
  • CSDN Markdown 编辑器语法大全
  • TCP/IP 协议【四次挥手】简要说明
  • 第11篇:网络安全协议
  • ES-入门-javaApi-文档-新增-删除
  • 【视频生成大模型】 视频生成大模型 THUDM/CogVideoX-2b
  • 【MR开发】在Pico设备上接入MRTK3(三)——在Unity中运行MRTK示例
  • C#中委托的应用与示例
  • 算法: 模拟题目练习
  • 软考中级科目怎么选?软考中级证书有什么用?
  • HTTP 请求的请求体是什么
  • 助力语音技术发展,景联文科技提供语音数据采集服务
  • PyTorch搭建神经网络入门教程
  • 你的电脑能不能安装windows 11,用这个软件检测下就知道了
  • BF 算法
  • SHOW-O——一款结合多模态理解和生成的单一Transformer
  • 缓存框架JetCache源码解析-缓存变更通知机制
  • Android 设置特定Activity内容顶部显示在状态栏底部,也就是状态栏的下层 以及封装一个方法修改状态栏颜色
  • 用自己的数据集复现YOLOv5
  • 如何在博客中插入其他的博客链接(超简单)最新版
  • JS通过递归函数来剔除树结构特定节点
  • javayufa
  • 软考-高级系统分析师知识点-补充篇
  • JavaScript全面指南(四)
  • 2024年诺贝尔物理学奖的创新之举
  • FileLink内外网文件交换——致力企业高效安全文件共享
  • 使用Python在Jupyter Notebook中显示Markdown文本
  • G1 GAN生成MNIST手写数字图像
  • WPFDeveloper正式版发布
  • 实现鼠标经过某个元素时弹出提示框(通常称为“工具提示”或“悬浮提示”)