Day3:Windows网络编程-UDP

news/2024/11/7 18:41:31/

  对比TCP与UDP的通信区别

 UDP Server没有listen()和accept()

TCP Server

#include <iostream>
#include <WinSock2.h>
// 包含网络库
#pragma comment(lib,"ws2_32.lib")
using namespace std;int main()
{// 1. 初始化套接字 初始化套接字库cout << "UDP Server" << endl;WORD wVersion;WSADATA wsaData;int err;wVersion = MAKEWORD(1, 1);err = WSAStartup(wVersion, &wsaData);if (err != 0){return err;}if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1){WSACleanup();return -1;}// 2. 创建套接字SOCKET sockSrv = socket(AF_INET,SOCK_DGRAM,0);if (INVALID_SOCKET == sockSrv) //加入容错机制 {printf("socket errorNo = %d\n",GetLastError());return -1;}// 3.分配地址和端口SOCKADDR_IN addrSrv;// h:host to n:net l:long 主机字节序转换为网络字节序addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); addrSrv.sin_family = AF_INET;addrSrv.sin_port = htons(6001);if(SOCKET_ERROR == bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR_IN))){printf("bind errorNo = %d\n",GetLastError());return -1;}// 4. 等待接收数据SOCKADDR_IN addrCli; // 目的套接字地址族int len = sizeof(SOCKADDR_IN);char recvBuf[100] = {0};char sendBuf[100] = {0};while(true){recvfrom(sockSrv, recvBuf, 100, 0, (SOCKADDR*)&addrCli, &len);cout << recvBuf << endl;sprintf_s(sendBuf, 100, "Ack:%s", recvBuf);sendto(sockSrv, sendBuf,strlen(sendBuf) + 1,0, (SOCKADDR*)&addrCli, len);}// 5. 关闭套接字closesocket(sockSrv);WSACleanup();system("pause");return 0;
}

代码逻辑:

  1. 初始化套接字 初始化套接字库
  2. 创建套接字
  3. 分配地址和端口
  4. bind() 分配地址和端口
  5. 等待接收数据 recvfrom()接收数据 sendto()发送数据  while循环

TCP Client

#include <iostream>
#include <WinSock2.h>
// 包含网络库
#pragma comment(lib,"ws2_32.lib")
using namespace std;int main()
{// 1. 初始化套接字 初始化套接字库cout << "UDP Client" << endl;WORD wVersion;WSADATA wsaData;int err;wVersion = MAKEWORD(1, 1);err = WSAStartup(wVersion, &wsaData);if (err != 0){return err;}if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1){WSACleanup();return -1;}// 2. 创建UDP套接字SOCKET sockCli = socket(AF_INET, SOCK_DGRAM, 0);if (INVALID_SOCKET == sockCli) //加入容错机制 {printf("socket errorNo = %d\n", GetLastError());return -1;}// 3. 填充地址和端口SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");addrSrv.sin_family = AF_INET;addrSrv.sin_port = htons(6001);int len = sizeof(SOCKADDR_IN);char sendBuf[100] = "hello";char recvBuf[100] = { 0 };// 4.发送UDP数据sendto(sockCli, sendBuf, strlen(sendBuf) + 1,0,(SOCKADDR*)&addrSrv, len);// 5.接收UDP数据recvfrom(sockCli,recvBuf,100,0,(SOCKADDR*)&addrSrv,&len);cout << recvBuf << endl;closesocket(sockCli);system("pause");return 0;
}

代码逻辑:

  1. 初始化套接字 初始化套接字库
  2. 创建UDP套接字
  3. 填充地址和端口
  4. 直接发送/接收数据

运行结果:

关于bind()函数

官方文档:绑定函数将本地地址与套接字相关联。

int bind(
  [in] SOCKET         s,
       const sockaddr *addr,
  [in] int            namelen
);

bind()是一个用于将套接字(socket)与特定的网络地址(IP 地址和端口号)绑定的函数。它在套接字创建后,但在进行网络通信之前被调用。

三个参数的含义:

  • sockfd:需要绑定的套接字描述符(socket descriptor)。
  • addr:指向要绑定的网络地址的结构体指针,通常是 struct sockaddr 或其派生结构体的指针。
  • addrlen:网络地址结构体的长度。

关于sendto()函数

官方文档:

sendto 函数将数据发送到特定目标。

int WSAAPI sendto(
  [in] SOCKET         s,
  [in] const char     *buf,
  [in] int            len,
  [in] int            flags,
  [in] const sockaddr *to,
  [in] int            tolen
);

sendto() 是用于发送数据到指定目标地址的函数,通常用于无连接的数据报套接字(SOCK_DGRAM)。它可以向指定的目标地址发送数据,并指定数据的长度和其他参数。

参数的含义:

  • s:要发送数据的套接字描述符(socket descriptor)。
  • buf:指向包含要发送的数据的缓冲区的指针。
  • len:要发送的数据的长度。
  • flags:发送标志,用于控制发送操作的行为,例如是否启用特定的选项。
  • to:指向目标地址的结构体指针,通常是 struct sockaddr 或其派生结构体的指针。
  • tolen:目标地址结构体的长度。

关于recvfrom()函数

官方文档:

recvfrom 函数接收数据报并存储源地址。

int recvfrom(
  [in]                SOCKET   s,
  [out]               char     *buf,
  [in]                int      len,
  [in]                int      flags,
  [out]               sockaddr *from,
  [in, out, optional] int      *fromlen
);

recvfrom() 是用于接收来自指定源地址的数据的函数,通常用于无连接的数据报套接字(SOCK_DGRAM)。它可以从指定的源地址接收数据,并存储到指定的缓冲区中。

参数含义:

  • s:要接收数据的套接字描述符(socket descriptor)。
  • buf:指向接收数据的缓冲区的指针。
  • len:缓冲区的长度,即最大接收的字节数。
  • flags:接收标志,用于控制接收操作的行为,例如是否启用特定的选项。
  • from:指向存储源地址的结构体的指针,通常是 struct sockaddr 或其派生结构体的指针。
  • fromlen:指向存储源地址结构体长度的整型指针。

http://www.ppmy.cn/news/97914.html

相关文章

Kubernetes 云原生 Gateway 网关

一、云原生定义 CNCF 对云原生的定义中提到了几个关键的点&#xff1a; 1、强调应用环境的动态性&#xff0c;像公有云、私有云、混合云等新型的动态环境已成为大多数应用的首选&#xff1b; 2、强调在跨多云部署应用时具备非云平台绑定的属性&#xff1b; 3、还强调了弹性扩展…

JavaSE_day39(接上File:获取,修改,数组形式获取,获取目录下的java文件,删除目录。回顾以及深入完整介绍IO,使用字符、字节复制文本文件)

1 A.java * 4 File获取功能 ①&#xff1a;获取绝对路径 File getAbsoluteFile() * String getAbsolutePath() * ②&#xff1a;获取父目录&#xff0c;文件名&#xff08;最后的一个的目录或者文件&#xff09; * String …

Windows SSH远程连接Linux服务器 - 无公网IP内网穿透

文章目录 前言视频教程1、安装OpenSSH2、vscode配置ssh3. 局域网测试连接远程服务器4. 公网远程连接4.1 ubuntu安装cpolar内网穿透4.2 创建隧道映射4.3 测试公网远程连接 5. 配置固定TCP端口地址5.1 保留一个固定TCP端口地址5.2 配置固定TCP端口地址5.3 测试固定公网地址远程 转…

Unity的IPreprocessComputeShaders:深入解析与实用案例

Unity IPreprocessComputeShaders Unity IPreprocessComputeShaders是Unity引擎中的一个非常有用的功能&#xff0c;它可以让开发者编译Compute Shader时自定义哪些操作需要被执行。这个可以帮助开发者更好地控制Compute Shader的编译过程&#xff0c;确保在编译Compute Shade…

K8s环境使用Triton实现云端模型推理

前置条件&#xff1a;K8集群、helm 1、以模型名作为目录名&#xff0c;创建目录 mkdir resnet50_pytorch 2、将模型文件、配置文件&#xff08;输入、输出等&#xff09;存到刚创建的目录下&#xff0c;resnet50_pytorch目录下文件层级结构如下 model-respository/ └── …

vue3.0与vue2.0

一、生命周期的变化 1.vue2.响应式架构 2.vue3.0 响应式架构图 Vue3.0响应式框架在设计上&#xff0c;将视图渲染和数据响应式完全分离开来。将响应式核心方法effect从原有的Watcher中抽离。这样&#xff0c;当我们只需要监听数据响应某种逻辑回调(例如监听某个text属性的变化…

(数字图像处理MATLAB+Python)第七章图像锐化-第三节:高斯滤波与边缘检测

文章目录 一&#xff1a;高斯函数&#xff08;1&#xff09;定义&#xff08;2&#xff09;特点 二&#xff1a;LOG算子&#xff08;1&#xff09;定义&#xff08;2&#xff09;程序 三&#xff1a;Canny算子&#xff08;1&#xff09;最优边缘检测&#xff08;2&#xff09;C…

Redis系列--redis持久化

一、为什么需要持久化 redis本身运行时数据保存在内存中&#xff0c;如果不进行持久化&#xff0c;那么在redis出现非正常原因宕机或者关闭redis的进程或者关闭计算机后数据肯定被会操作系统从内存中清掉。当然&#xff0c;redis本身默认采用了一种持久化方式&#xff0c;即RD…