网络套接字编程(UDP协议)

news/2024/4/19 6:20:16/文章来源:https://blog.csdn.net/zjq_love/article/details/128095393

文章目录

    • 预备知识
    • socket(网络套接字)编程接口
    • 简单的UDP网络程序
    • 增加多用户可以互相通信

预备知识

网络字节序
大端存储:数据的高字节内容保存在内存的低地址处,数据的低字节内容保存在内存的高地址处
小端存储:数据的高字节内容保存在内存的高地址处,数据的低字节内容保存在内存的低地址处

内存中的多字节数据相对于内存地址有大端和小端之分, 磁盘文件中的多字节数据相对于文件中的偏
移地址也有大端小端之分, 网络数据流同样有大端小端之分. 那么如何定义网络数据流的地址呢?

网络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是高地址.
TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节.

不管这台主机是大端机还是小端机, 都会按照这个TCP/IP规定的网络字节序来发送/接收数据;

如果当前发送主机是小端, 就需要先将数据转成大端; 否则就忽略, 直接发送即可

网络字节序和主机字节序的转换

#include <arpa/inet.h>uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

这些函数名很好记,h表示host,n表示network,l表示32位长整数,s表示16位短整数。
例如htonl表示将32位的长整数从主机字节序转换为网络字节序,例如将IP地址转换后准备发送。
如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回;

如果主机是大端字节序,这些函数不做转换,将参数原封不动地返回。

socket(网络套接字)编程接口

// 创建 socket 文件描述符 
int socket(int domain, int type, int protocol);// 绑定端口号 
int bind(int socket, const struct sockaddr *address, socklen_t address_len);

sockaddr结构
socket API是一层抽象的网络编程接口,适用于各种底层网络协议,如IPv4、IPv6,然而, 各种网络协议的地址格式并不相同.

在这里插入图片描述

简单的UDP网络程序

socket函数

int socket(int domain, int type, int protocol);

参数说明:

domain:创建套接字的域或者叫做协议家族,也就是创建套接字的类型。该参数就相当于struct sockaddr结构的前16个位。如果是本地通信就设置为AF_UNIX,如果是网络通信就设置为AF_INET(IPv4)或AF_INET6(IPv6)。

type:创建套接字时所需的服务类型。其中最常见的服务类型是SOCK_STREAM和SOCK_DGRAM,如果是基于UDP的网络通信,我们采用的就是SOCK_DGRAM,叫做用户数据报服务,如果是基于TCP的网络通信,我们采用的就是SOCK_STREAM,叫做流式套接字,提供的是流式服务。

protocol:创建套接字的协议类别。你可以指明为TCP或UDP,但该字段一般直接设置为0就可以了,设置为0表示的就是默认,此时会根据传入的前两个参数自动推导出你最终需要使用的是哪种协议。

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数说明:

sockfd:创建套接字返回的文件描述符
addr:网络相关的属性
传入的addr的长度

struct sockaddr_in{__SOCKADDR_COMMON (sin_);in_port_t sin_port;			/* Port number.  */struct in_addr sin_addr;		/* Internet address.  *//* Pad to size of `struct sockaddr'.  */unsigned char sin_zero[sizeof (struct sockaddr) -__SOCKADDR_COMMON_SIZE -sizeof (in_port_t) -sizeof (struct in_addr)];};

sin_port:表示端口号
sin_family:表示协议家族
sin_addr:表示IP地址

字符串转in_addr

in_addr_t inet_addr(const char *cp);

服务器绑定

class udpServer
{udpServer(uint16_t port, string ip = "") : _port(port), _ip(ip){}void init(){//1. 创建套接字_sockfd = socket(AF_INET,SOCK_DGRAM,0);if(_sockfd < 0){logmessage("error");exit(1);}logmessage("socket create sucessfully");// 2. 创建ip与端口号struct sockaddr_in local;memset(&local,0,sizeof(local));local.sin_family = AF_INET;local.sin_port=htons(_port);// INADDR_ANY表示让服务器端计算机上的全部网卡的IP地址均可以做为服务器IP地址local.sin_addr.s_addr =  _ip.empty() ?  htonl(INADDR_ANY)  :inet_addr(_ip.c_str());socklen_t len = sizeof(local);//3.连接if(bind(_sockfd,(struct sockaddr*)&local,len) == -1) {logmessage("bind error");exit(2);}logmessage("bind sucessfully");}
private:int _sockfd; //套接字uint16_t _port;  // 端口号string _ip; // ip地址
};

服务器读取用户发来的数据

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, 
struct sockaddr *src_addr, socklen_t *addrlen);

参数说明:

sockfd:对应操作的文件描述符。表示从该文件描述符索引的文件当中读取数据。
buf:读取数据的存放位置。
len:期望读取数据的字节数。
flags:读取的方式。一般设置为0,表示阻塞读取。
src_addr:对端网络相关的属性信息,包括协议家族、IP地址、端口号等。
addrlen:调用时传入期望读取的src_addr结构体的长度,返回时代表实际读取到的src_addr结构体的长度,这是一个输入输出型参数。

服务器接收用户信息

message.hpp

struct message
{/* data */message(){_time=(uint64_t)time(nullptr);}friend ostream& operator<<(ostream& out,const message& mess);char _name[10];char _message[1024];uint64_t _time;
};ostream& operator<<(ostream& out,const message& mess)
{out<<"时间:"<<mess._time<<"用户名:"<<mess._name<<endl;out<<mess._message<<endl;return out;
}
void start()
{message mess;struct sockaddr_in client;socklen_t len = sizeof(client);memset(&client,0,sizeof(client));while(1){ssize_t s = recvfrom(_sockfd,&mess,sizeof(mess),0,(struct sockaddr*)&client,&len);if(s < 0){logmessage("recvfrom error");continue;}logmessage("recvfrom sucess");cout<<mess;}
}

客户端创建套接字

class udpClient
{public:udpClient(const string &serip, uint16_t serport) : _serip(serip), _serport(serport){//创建套接字_sockfd = socket(AF_INET, SOCK_DGRAM, 0);}private:int _sockfd; // 套接字string _serip;     // 服务器ipuint16_t _serport; // 服务器port
};

为什么客户端不需要绑定
所谓的"不需要",指的是: 不需要用户自己bind端口信息!因为OS会自动给你绑定,推荐这么做

sendto函数

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, 
const struct sockaddr *dest_addr, socklen_t addrlen);

参数说明:

sockfd:对应操作的文件描述符。表示将数据写入该文件描述符索引的文件当中。
buf:待写入数据的存放位置。
len:期望写入数据的字节数。
flags:写入的方式。一般设置为0,表示阻塞写入。
dest_addr:对端网络相关的属性信息,包括协议家族、IP地址、端口号等。
addrlen:传入dest_addr结构体的长度。

客户端发送消息

void communicate()
{message mess;struct sockaddr_in server;server.sin_family = AF_INET;server.sin_port = htons(_serport);server.sin_addr.s_addr = inet_addr(_serip.c_str());cout<<"请输入你的名字"<<endl;cin>>mess._name;while (1){cout<<"请输入你要发的消息"<<endl;cin>>mess._message;sendto(_sockfd, &mess, sizeof(mess), 0, (struct sockaddr *)&server, sizeof(server));}
}

效果:在这里插入图片描述

增加多用户可以互相通信

class udpServer
{
public:void start(){message mess;struct sockaddr_in client;socklen_t len = sizeof(client);memset(&client,0,sizeof(client));while(1){ssize_t s = recvfrom(_sockfd,&mess,sizeof(mess),0,(struct sockaddr*)&client,&len);if(s < 0){logmessage("recvfrom error");continue;}logmessage("recvfrom sucess");cout<<mess;// 给其他用户聊天发送信息messageRoutine(mess);string ip_port;ip_port+=to_string(ntohl(client.sin_addr.s_addr));ip_port+=to_string(ntohs(client.sin_port));users.insert({ip_port,client});}}
private:
void messageRoutine(const message& mess){for(auto user:users){sendto(_sockfd,&mess,sizeof(mess),0,(struct sockaddr*)&(user.second),sizeof(user.second));}}private:int _sockfd; //套接字uint16_t _port;  // 端口号string _ip; // ip地址unordered_map<string,struct sockaddr_in> users; // 所有的用户
};
class udpClient
{public:udpClient(const string &serip, uint16_t serport) : _serip(serip), _serport(serport){//创建套接字_sockfd = socket(AF_INET, SOCK_DGRAM, 0);}void communicate(){pthread_t t;pthread_create(&t,nullptr,ReadMessage,(void*)&_sockfd);pthread_detach(t);message mess;struct sockaddr_in server;server.sin_family = AF_INET;server.sin_port = htons(_serport);server.sin_addr.s_addr = inet_addr(_serip.c_str());cout<<"请输入你的名字"<<endl;cin>>mess._name;cout<<"开始通信"<<endl;while (1){cin>>mess._message;sendto(_sockfd, &mess, sizeof(mess), 0, (struct sockaddr *)&server, sizeof(server));}}~udpClient(){}
private:
static void* ReadMessage(void* args)
{int socket = *(int*)args;message mess;struct sockaddr_in tmp;socklen_t len=sizeof(tmp);while(1){recvfrom(socket,&mess,sizeof(mess),0,(sockaddr*)&tmp,&len);cout<<mess<<endl;}
}private:int _sockfd; // 套接字string _serip;     // 服务器ipuint16_t _serport; // 服务器port
};

效果:
在这里插入图片描述
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

global关键字、python实现ATM简单功能

目录 一.局部变量、全局变量 二.global关键字 演示 三.编写ATM程序 要求 详细步骤 存在问题 改进 完整代码 一.局部变量、全局变量 1.什么是局部变量 作用范围在函数内部&#xff0c;在函数外部无法使用 2.什么是全局变量 在函数内部和外部均可使用 3.如何将函数内定…

[附源码]SSM计算机毕业设计校园自行车租售管理系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

高等数学(第七版)同济大学 习题10-3 (前9题)个人解答

高等数学&#xff08;第七版&#xff09;同济大学 习题10-3&#xff08;前9题&#xff09; 函数作图软件&#xff1a;Mathematica 1.化三重积分I∭Ωf(x,y,z)dxdydz为三次积分&#xff0c;其中积分区域Ω分别是\begin{aligned}&1. \ 化三重积分I\iiint_{\Omega}f(x, \ y, …

【C++】类型转换

目录 一、C语言风格类型转换 二、C风格类型转换 1.static_case 2.reinterpret_case 3、const_case 4、dynamic_case 三、RTTI 总结 一、C语言风格类型转换 在C语言中&#xff0c;如果赋值运算符左右两侧类型不同&#xff0c;或者形参与实参类型不匹配&#xff0c;或者返…

【正点原子FPGA连载】 第二十章 LCD触摸屏实验摘自【正点原子】DFZU2EG/4EV MPSoC 之FPGA开发指南V1.0

1&#xff09;实验平台&#xff1a;正点原子MPSoC开发板 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id692450874670 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第二十章 LCD触摸…

Vue.js 加入高德地图的实现方法

一、功能需求 1.根据输入内容进行模糊查询&#xff0c;选择地址后在地图上插上标记&#xff0c;并更新经纬度坐标显示 2.在地图点击后&#xff0c;根据回传的左边更新地址信息和坐标显示 二、准备 1.申请高德地图账号&#xff0c;创建应用 2.在应用管理中 获得key 和安全密…

[附源码]Python计算机毕业设计Django常见Web漏洞对应POC应用系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

Python学习:json对象与string相互转换教程

首先要明确&#xff0c;python里有json这个库&#xff0c;但并没有json这个类&#xff0c;所以所谓的json对象本质上就是一个dict&#xff1b;而json这个库&#xff0c;用于实现dict到string、string到dict的互转。 更具体一点&#xff0c;json对象&#xff08;dict&#xff0…

Linux网络编程——IO多路复用

文章目录1&#xff0c;I/O模型2&#xff0c;阻塞I/O 模式2.1&#xff0c;读阻塞&#xff08;以read函数为例&#xff09;2.2&#xff0c;写阻塞3&#xff0c;非阻塞I/O模式3.1&#xff0c;非阻塞I/O模式的实现&#xff08;fcntl()函数、ioctl() 函数&#xff09;3.1.1&#xff…

leetcode 343. 整数拆分(动态规划)

题目链接&#xff1a;343. 整数拆分 动态规划 (1) 确定 dpdpdp 数组下标含义&#xff1a; dp[i]dp[i]dp[i]: 将 iii 拆分为至少两个正整数之后的最大乘积&#xff1b; (2) 确定递推公式&#xff1a; 当 i≥2i \ge 2i≥2 时, 设 jjj 是 iii 拆分出来的第一个正整数&#xff0c…

关于uni-app小程序接入微信登录

https://uniapp.dcloud.net.cn/api/plugins/login.html#login 官网上有关于uni.login()的说明&#xff0c;如果是要微信登录&#xff0c;则需要wx.login()。 小程序登录 | 微信开放文档 如下图&#xff0c;在小程序管理平台生成AppSecret&#xff0c;同时将AppId在HubilderX中…

swift @State @Published @ObservedObject sink

State struct ContentView: View {State private var isRain truevar body: some View {VStack {Image(systemName: isRain ? "cloud.rain.fill" : "sun.max.fill").resizable().frame(width: 100, height: 100)Text(isRain ? "我們淋著大雨不知何…

【PS-7】移动工具

目录 移动工具快捷键【v】&#xff08;英文状态&#xff09; 多文件间拖拽图层对象 快捷键【ALT】复制图层 【ALTSHIFT】只能垂直/水平/45角地去复制图层 4个方向键可以微调图层的位置 变换控件 对齐分布 【题外话】设置参考线颜色 【题外话】快捷键【F12】让已经动过…

实验三-----数据库

一、实验目的 1.掌握SQL Server Management Studio中SQL 查询操作&#xff1b; 2.掌握SQL 的单表查询命令&#xff1b; 3.掌握SQL 的连接查询操作&#xff1b; 4.掌握SQL 的嵌套查询操作&#xff1b; 5.掌握SQL 的集合查询操作。 二、实验环境 1&#xff0e;实验室名称&…

[附源码]计算机毕业设计springboot海南琼旅旅游网

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

前端单元测试,更进一步

前端测试2022 如果从 2014 年 Jest 的第一个版本发布开始计算&#xff0c;前端开发领域工程化的单元测试能力已经发展了八年有余。Jest 集成了 Jasmine 等以往各种被证明有效的单元测试框架和断言等工具&#xff0c;也可以用来完成包含外部接口服务的集成测试等。最近几年热门的…

xxl-job安装部署

一、简介 XXL-JOB是一个分布式任务调度平台&#xff0c;其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线&#xff0c;开箱即用。 中文文档English Documentation 二、安装 xxl-job需要的提前安装好以下环境&#xff1a;jdk、m…

INTERSPEECH 2022|CALM: 基于对比学习的表现力语音合成跨模态说话风格建模【语音之家】

本文由清华大学与腾讯科技有限公司和香港中文大学合作&#xff0c;并 在腾讯公司落地应用 。 说话风格建模对于表现力语音合成具有重要作用。 现有基于参考音频提取风格表征的方法通常利用文本的语义相似度进行参考音频选择&#xff0c;忽略了语义信息和说话风格的差异性。 本文…

大厂都在用MyBatis,跳槽的时候MyBatis更是面试必问的内容,那你对于MyBatis又掌握了多少呢?这份MyBatis源码解析值得拥有!

MyBatis作为一个流行的半自动ORM框架&#xff0c;里面融合了许多优秀的设计理念&#xff0c;分析其源码骨架能够帮你建立良好的项目设计经验。由于其比较复杂&#xff0c;我会分成几篇来讲&#xff0c;一起踏上征服的旅程吧&#xff01; 首先把MyBatis源码包导入到idea&#x…

python+django汽车租赁系统pycharm项目

目录 1 绪论 1 1.1课题背景 1 1.2课题研究现状 1 1.3初步设计方法与实施方案 2 1.4本文研究内容 2 4 2.3 B/S结构简介 4 2.4MySQL数据库 5 3 系统分析 6 3.1系统可行性分析 6 3.1.1经济可行性 6 3.1.2技术可行性 6 3.1.3运行可行性 6 3.2系统现状分析 6 3.3功能需求分析 7 …