Winsock编程实例---TCP&UDP

2023-05-16

0x1 基于TCP的通信

1、服务端

1.1 创建基本流程
创建一个TCP服务端的程序需要调用的函数流程:

  1. 初始化函数库 >> WSAStartup()
  2. 创建套接字 >> socket()
  3. 绑定套接字 >> bind()
  4. 监听端口 >> listen()
  5. 获取连接请求 >> accept()
  6. 发送或者接收数据 >> send()
  7. Winsock库的释放 >> WSACleanup()

1.2 代码实现

(1) 初始化函数库

WSADATA wsaData;
WSAStartup(MAKEWORD(2,2),&wsaData);

说明:WSAStartup的参数1->初始化winsock库的版本号;参数2-> 指向WSADATA的指针,而这个结构体用来存储WSAStartup函数调用后返回WindowsSockets数据。在程序的开始处调用该初始化函数,在程序中就可以使用Winsock相关的所有API函数。
(2) 创建套接字

SOCKET sListen = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);

说明:socket()函数参数1-> 指定协议族,在windows下使用的有两个,AF_INET,PF_INET,这两个宏在Winsock2.h的定义是相同的。一般在调用socket()函数时应该使用PF_INET,而在设置地址时使用AF_INET。
参数2 -> 指定新套接字描述符的类型,一般使用的有3个,分别是SOCK_STREAM,SOCK_DGRAM和SOCK_RAW,分别是流套接字,数据包套接字和原始协议接口。
参数3 -> 这里用来指定应用程序所使用的通信协议,可以使用的IPPROTO_TCP、IPPROTO_UDP,IPPROTO_ICMP等。此参数是根据参数2值进行选择。这里参数2使用的是SOCK_STREAM,所以参数3使用IPPROTO_TCP。
(3) 绑定套接字与地址信息

struct sockaddr_in ServerAddr; 
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_addr.S_un.S_addr = inet_addr("192.168.41.1");  //将点分十进制IP转换为长整数型数
ServerAddr.sin_port = htons(1234);                           //htons将整形变量从主机字节序转换为网络字节序
bind(sListen,(SOCKADDR *)&ServerAddr,sizeof(ServerAddr));

说明:socket()函数可以创建新的套接字描述符,但它只是一个描述符,为网络资源做准备。要真正在网络中通信,需要本地的地址与本地的端口号信息。 通过bind函数进行信息的绑定,而bind函数的3个参数当中最重要当属参数2。
它是sockaddr的结构体,该结构体有16个字节,在该结构体之前使用sockaddr_in,为bind函数指定地址和端口时,向sockaddr_in结构体填充相应的内容。

Struct sockaddr_in{
	Short sin_family;
	u_short sin_port;
	struct in_addr sin_addr;
	char sin_zero[8];
};

而这里我们要此结构体的sin_family成员,它的取值有三种:
AF_UNIX(本机通信)
AF_INET(TCP/IP - IPv4)
AF_INET6(TCP/IP – IPv6)
(4) 监听端口

listen(sListen,SOMAXCONN);

说明:参数2 -> 定义了系统中每一个端口最大的监听队列的长度
(5) 获取连接请求

sockaddr_in ClientAddr;
int nSize = sizeof(ClientAddr);
SOCKET sClient = accept(sLisent,(SOCKADDR *)&ClientAddr,&nSize);

说明:accept从请求队列中获取连接信息,创建新的套接字描述符,获取客户端地址。
参数1-> 处于监听端套接字描述符
参数2-> 指向sockaddr结构体的指针,用来返回客户端的地址信息。
参数3-> 客户端sockaddr结构体的大小
(6) 到这里服务端的操作基本完成,只需等待客户端的连接,然后就可以进行数据传输了。

1.3 完整代码

#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32")
int main()
{
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2,2),&wsaData);
	//创建套接字
	SOCKET sListen = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
	//对sockaddr_in结构体填充地址,端口等信息
	struct sockaddr_in ServerAddr; 
	ServerAddr.sin_family = AF_INET;
	ServerAddr.sin_addr.S_un.S_addr = inet_addr("192.168.41.1");  //将点分十进制IP转换为长整数型数
	ServerAddr.sin_port = htons(1234);                           //htons将整形变量从主机字节序转换为网络字节序
	
	//绑定套接字与地址信息
	bind(sListen,(SOCKADDR *)&ServerAddr,sizeof(ServerAddr));
	//端口监听
	listen(sListen,SOMAXCONN);
	//获取连接请求
	sockaddr_in ClientAddr;
	int nSize = sizeof(ClientAddr);
	
	SOCKET sClient = accept(sListen,(SOCKADDR *)&ClientAddr,&nSize);
	//输出客户端使用的IP地址和端口号
	printf("ClientIP=%s:%d\r\n",inet_ntoa(ClientAddr.sin_addr),ntohs(ClientAddr.sin_port));
	
	//ntohs()是一个函数名,作用是将一个16位数由网络字节顺序转换为主机字节顺序
	
	//发送消息
	char szMsg[MAXBYTE] = {0};
	lstrcpy(szMsg,"Hello Client!\r\n");
	send(sClient,szMsg,strlen(szMsg)+sizeof(char),0);
	//strlen测长和sizeof测长
	
	//接受消息
	recv(sClient,szMsg,MAXBYTE,0);
	printf("Client Msg :%s \r\n",szMsg);
	
	WSACleanup();
	
	return 0;
}

2、客户端

2.1 基本流程
客户端和服务端调用的API基本相同:
WSAStartup() -> socket() -> connect() -> send()/recv() -> closesocket() -> WSACleanup()
2.2 代码实现
客户端只需要创建套接字然后填充sockaddr_in结构体的地址和端口等信息即可。

struct sockaddr_in ServerAddr;
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_addr.S_un.S_addr = inet_addr("192.168.41.1");
ServerAddr.sin_port = htons(1234);

此处填充的信息为需要连接的服务端的信息。

2.3 完整代码

#include <stdio.h>
#include <winsock2.h>
#pragma comment (lib,"ws2_32")
int main()
{
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2,2),&wsaData);
	
	//创建套接字
	SOCKET sServer = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);

	//对sockaddr_in结构体填充地址、端口等信息
	struct sockaddr_in ServerAddr;
	ServerAddr.sin_family = AF_INET;
	ServerAddr.sin_addr.S_un.S_addr = inet_addr("192.168.41.1");
	ServerAddr.sin_port = htons(1234);
	
	//连接服务器 
	connect(sServer,(SOCKADDR *)&ServerAddr,sizeof(ServerAddr));
	
	char szMsg[MAXBYTE] = {0};

	//接收消息
	recv(sServer,szMsg,MAXBYTE,0);
	printf("Server Msg: %s \r\n",szMsg);

	//发送消息
	lstrcpy(szMsg,"Hello Server!!!\r\n");
	send(sServer,szMsg,sizeof(szMsg)+sizeof(char),0);

	WSACleanup();

	return 0;
}

0x2 基于UDP的通信

1、服务端

基于UDP协议的服务端程序不会去监听端口和等待请求连接,因此UDP协议的服务端程序会较短。

#include <stdio.h>
#include <winsock2.h>
#pragma comment (lib,"ws2_32")
int main()
{
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2,2),&wsaData);

	//创建套接字
	SOCKET sServer = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
	//对sockaddr_in结构体填充地址、端口等信息
	struct sockaddr_in ServerAddr;
	ServerAddr.sin_family = AF_INET;
	ServerAddr.sin_addr.S_un.S_addr = inet_addr("192.168.41.1");
	ServerAddr.sin_port = htons(1245);  //htons将整形变量从主机字节序转变为网络字节序
	//绑定套接字与地址信息
	bind(sServer,(SOCKADDR *)&ServerAddr,sizeof(ServerAddr));
	//接受消息
	char szMsg[MAXBYTE] = {0};
	struct sockaddr_in ClientAddr;
	int nSize = sizeof(ClientAddr);
	recvfrom(sServer,szMsg,MAXBYTE,0,(SOCKADDR *)&ClientAddr,&nSize);
	printf("Client Msg:%s \r\n",szMsg);
	printf("ClientIP = %s:%d\r\n",inet_ntoa(ClientAddr.sin_addr),ntohs(ClientAddr.sin_port));
	//发送消息
	lstrcpy(szMsg,"Hello Client,this is Server!\r\n");
	nSize = sizeof(ClientAddr);
	sendto(sServer,szMsg,strlen(szMsg)+sizeof(char),0,(SOCKADDR *)&ClientAddr,nSize);

	WSACleanup();
	return 0;
}

2、客户端

基于UDP客户端的代码相对于TCP协议的客户端代码来讲,不需要调用connect()函数进行连接,省去了TCP协议的"三次握手"的过程,可以直接发送数据给服务器。

#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32")

int main()
{
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2,2),&wsaData);
	//创建套接字
	SOCKET sClient = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
	//对sockaddr_in结构体填充地址、端口等信息
	struct sockaddr_in = ServerAddr;
	ServerAddr.sin_family = AF_INET;
	ServerAddr.sin_addr.S_un.S_addr = inet_addr("10.10.30.12");
	ServerAddr.sin_port = htons(1234);
	
	//发送消息
	char szMsg[MAXBYTE] = {0};
	lstrcpy(szMsg,"Hello Server This is Client !");
	int nSize = sizeof(ServerAddr);
	sendto(sClient,szMsg,strlen(szMsg)+sizeof(char),0,(SOCKADDR *)&ServerAddr,nSize);
	//接收消息
	nSize = sizeof(ServerAddr);
	recvfrom(sClient,szMsg,strlen(szMsg)+sizeof(char),0,(SOCKADDR*)&ServerAddr,nSize);
	printf("Server Msg:%s \r\n",szMsg);
	
	WSACleanup();
	return 0;
}

学长的博客:https://blog.roachs.cn/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Winsock编程实例---TCP&UDP 的相关文章

  • ic_gvins编译及环境配置问题解决

    RTK VIO松组合 对惯导精度要求较高 1 环境配置和编译 安装依赖项 span class token comment gcc 8 span span class token function sudo span span class
  • EVO画图设置

    一 绘图设置 1 更改背景色和网格 span class token comment 白色网格 span evo config span class token builtin class name set span plot seabor
  • GINS_OB环境配置

    1 程序简介 武大开源GNSS INS松组合IMU预积分有考虑地球自传和不考虑两种形式可以灵活设置GNSS中断时间IMU可以和里程计进行融合 2 环境配置 span class token comment gcc 8 g 43 43 8 s
  • OB_GINS程序框架

    1 程序运行 span class token builtin class name cd span OB GINS span class token comment 编译好的可执行文件 xff1a bin ob gins xff0c 参数
  • KEIL、MDK中关于__LINE__宏 printf 的显示不正确的问题

    span class token operator gt span define span class token function DEBUG span span class token punctuation span log span
  • VINS-回环检测与重定位

    参考博客 pose graph分析1 pose graph分析2 pose graph分析3
  • 源码安装naviagtion,但是出现[move_base-2] process has died 运行错误的解决办法

    今天开始记录ros遇到的问题 安装navigation可以使用两种方法 第一种 xff1a sudo apt get install ros kinetic navigation 这种安装方法最简单 xff0c 新手或者不需要动naviag
  • linux---静态库和动态库的制作和使用

    静态链接和动态链接 静态链接 xff1a 生成可执行代码 xff0c 链接静态库 xff08 与代码位置有关的链接方式 xff09 xff0c 需要将代码拷贝到我们的源代码中才能运行 动态链接 xff1a 生成可执行代码 xff0c 链接动
  • 加一

    加一 描述 给定一个由整数组成的非空数组所表示的非负整数 xff0c 在该数的基础上加一 最高位数字存放在数组的首位 xff0c 数组中每个元素只存储单个数字 你可以假设除了整数 0 之外 xff0c 这个整数不会以零开头 示例 1 输入
  • STM32bootloader原理解释

    STM32bootloader原理解释 一 STM32的常规启动流程 STM32的内部flash地址起始于0x8000000 xff0c 一般情况下 xff0c 程序文件就从此地址开始写入 此外STM32是基于Cortex M3内核的微控制
  • 模糊PID基本原理及matlab仿真实现(新手!新手!新手!)

    有关模糊pid的相关知识就把自己从刚接触到仿真出结果看到的大部分资料总结一下 xff0c 以及一些自己的ps 以下未说明的都为转载内容 1 转自 https blog csdn net weixin 36340979 article det
  • VMware+ubuntu+win10笔记本实现笔记本连接WIFI且ubuntu既可以上网又能连接开发板

    背景 最近在学习imx6ull开发板的时候 xff0c 发现开发板通过网线连接笔记本电脑却无法ping通ubuntu xff0c 于是捣鼓了很久终于可以了 xff0c 却又发现ubuntu不能上网了 xff0c 经过一番查找资料和尝试 xf
  • 在windows上用vscode打造比vc++6.0好用的C/C++ IDE,适用编程小白

    准备 xff1a 1 安装MinGW xff0c 添加gcc gdb等编译调试工具bin目录 头文件Include目录 库lib的路径到系统环境变量 xff0c 安装LLVM 添 加Clang编译器所在bin目录到系统环境变量 具体操作百度
  • C语言数据结构——线性表的链式存储结构

    文章目录 线性表的链式存储结构1 基本概念2 设计与实现3 优点和缺点 线性表的链式存储结构 1 基本概念 链式存储定义 xff1a 为了表示每个数据元素与其直接后继元素之间的逻辑关系 xff0c 每个元素除了存储本身的信息之外 xff0c
  • 智能车浅谈——硬件篇

    目录 初识小车硬件系统1 电源系统线性电源开关电源 2 人机交互系统3 MCU最小系统4 传感器系统摄像头电感编码器 5 驱动系统 机械结构 17届完赛代码智能车系列文章汇总 前言 xff1a 作为一名老三本玩家 xff0c 笔者深知一些同
  • 智能车浅谈——图像篇

    文章目录 前言认识图像基本含义图像类型数字图像彩色图像灰度图像黑白图像 小结 图像处理图像压缩二值化固定阈值法大津法 图像降噪 xff08 腐蚀 xff09 寻边线 总结17届完赛代码17届完赛代码智能车系列文章汇总 前言 前面已经记录了智
  • 智能车浅谈——手把手让车跑起来(电磁篇)

    文章目录 前言材料准备备赛组车模硬件 练习组车模硬件方案 整车原理赛道信息获取及转向原理工字电感运放模块转向原理元素判断 电机及舵机控制原理 代码实现效果欣赏总结17届完赛代码智能车系列文章汇总 前言 电磁寻迹小车 之前智能车系列已经做了一
  • 手把手教你OneNET数据可视化

    文章目录 前言OneNET实现数据可视化效果一览发布项目 xff08 5 17更新 xff09 总结 前言 之前介绍了Hi3861使用MQTT协议接入OneNET实现数据的上传以及命令的下发 xff0c 本文主要是介绍一下如何使用OneNE
  • linux---进程间通信(ipc)之管道

    进程间通信方式 管道共享内存消息队列信号量本地套接字等等都能作为我们进程间通信的方法 操作系统提供进程间通信方式的原因 因为对于我们进程来说 xff0c 每一个进程都是相互独立的 xff0c 具有独立性 xff0c 如果我们需要两个不同的进
  • 嵌入式学习笔记——STM32的USART收发字符串及串口中断

    USART收发字符串及串口中断 前言字符串的收发发送一个字符串接收字符串需求 利用串口实现printf 中断中断是什么串口的接收中断以及空闲中断实现代码实现效果 总结M4系列目录 前言 上一篇中 xff0c 介绍了串口收发相关的寄存器 xf

随机推荐

  • 嵌入式学习笔记——PWM与输入捕获(下)

    输入捕获 前言输入捕获的概述框图输入通道部分比较捕获寄存器与事件生成 寄存器编程思路 实际需求配置流程打开对应的时钟配置GPIO为复用模式定时器的时基部分配置定时器输入通道部分配置定时器中断配置 代码 xff1a 运行效果 xff1a 需求
  • 嵌入式学习笔记——SPI通信的应用

    SPI通信的应用 前言屏幕分类1 3OLED概述驱动芯片框图原理图通信时序显示的方式页地址 列地址初始化指令 程序设计初始化代码初始化写数据与写命令清屏函数 初始化代码字符显示函数 总结M4系列目录 前言 上一篇中介绍了STM32的SPI通
  • 嵌入式学习笔记——IIC通信

    IIC通信 前言IIC概述通信特征物理拓扑结构IIC通信的流程IIC的特点 xff1a STM32的IIC通信GPIO模拟IICIIC的时序组成 xff08 主机对从机写入数据 xff09 1 起始信号2 器件地址与读写位3 从机应答信号5
  • 立创梁山派学习笔记——GPIO输出控制

    梁山派 前言开发板简介GD32F407ZGT6官方资源数据手册1 系统框图2 引脚复用表3 命名规则4 其他 用户手册固件库与PACK包 开发环境搭建立创官方的资料包资料齐活 xff0c 开发1 工程搭建2 使用寄存器点亮LEDGPIO数量
  • C51_day5:串口通信UART

    3 1 串口基本认知 串行接口简称串口 xff0c 也称串行通信接口或串行通讯接口 xff08 通常指COM接口 xff09 xff0c 是采用串行通信方式的扩展接口 串行接口 xff08 Serial Interface xff09 是指
  • 哈希表/哈希冲突及解决方法(较全)

    哈希表的概念请参阅他人文章 xff0c 关于哈希冲突的解决这篇文章基本都整理到了 xff0c 还有几个常见的面试题 解决hash冲突的几种方法 前导 xff08 题外话 xff09 xff1a 一 开放定址法 xff08 闭散列 xff09
  • 关于构造函数,拷贝构造函数,析构函数的调用顺序(1)

    导言 对象是由 底层向上 开始构造的 xff0c 当建立一个对象时 xff0c 首先调用基类的构造函数 xff0c 然后调用下一个派生类的构造函数 xff0c 依次类推 xff0c 直至到达派生类次数最多的派生次数最多的类的构造函数为止 因
  • vector的内存释放

    xff11 vector内存分配机制 C 43 43 中vector的一个特点是 xff1a 内存空间只会增长 xff0c 不会减小 即为了支持快速的随机访问 xff0c vector容器的元素以连续方式存放 xff0c 每一个元素都挨着前
  • MFC多人在线聊天室

    我已经在我的资源里上传了这个聊天室的代码了 基于MFC的C 43 43 的select模型的TCP聊天室 采用select网络模型 xff0c 支持多人同时登陆 xff0c 功能有上线 下线 群聊 私聊 使用CjsonObject进行数据传
  • linux---进程间通信(ipc)之共享内存

    前面我们讲解了进程间通信之管道 xff0c 这段我们讲解我们的共享内存 共享内存是所有进程间通信方式最快的一种 内存共享模型就像下面的图一样 xff0c 就是将物理内存映射到我们进程的虚拟地址上 xff0c 我们就可以直接操作我们虚拟地址空
  • Effective C++总结

    explicit关键字 C 43 43 中的explicit关键字只能用于修饰只有一个参数或者是其他参数有默认值的类构造函数 它的作用是表明该构造函数是显式的 而非隐式的 跟它相对应的另一个关键字是implicit 意思是隐藏的 类构造函数
  • 计算机网络(5)TCP之重传机制

    重传机制 超时重传数据包丢失确认应答丢失 快速重传SACKD SACK例一 ACK 丢包例2 xff1a 网络延时 TCP 是通过序列号 确认应答 重发控制 连接管理以及窗口控制等机制实现可靠性传输的 TCP 实现可靠传输的方式之一 xff
  • 中断与回调

    1 xff0c 回调函数 回调函数的原理是使用函数指针实现类似 软中断 的概念 比如在上层的两个函数A和B xff0c 把自己的函数指针传给了C xff0c C通过调用A和B的函数指针达到 当做了什么 xff0c 通知上层来调用A或者B 的
  • CUDA 程序的优化(3) 任务划分

    4 3 1任务划分原则 首先 xff0c 需要将要处理的任务划分为几个连续的步骤 xff0c 并将其划分为CPU端程序和GPU端程序 划分时需要考虑的原则有 列出每个步骤的所有可以选择的算法 xff0c 并比较不同算法在效率和计算复杂度上的
  • C++ Matlab混合编程时“函数或变量 ‘matlabrc‘ 无法识别”

    在QT中调用Matlab初始化时 xff0c 出现了 函数或变量 matlabrc 无法识别 的情况 xff0c 接着崩溃 而且比较神奇的是 xff0c 前一次是可以初始化的 xff0c 但运行过程中发生了崩溃 直接搜解决办法 xff0c
  • Notepad++全选一整列的靠谱办法

    遇到行数较少的可以直接按住ALT手动选取 xff0c 但遇到行数较多 xff0c 就得这么干 xff1a 鼠标放在第一行某一列 xff0c 按住Alt 43 Shift xff0c 然后鼠标选择最后一行该列 xff0c 输入内容即可 xff
  • 对象转xml格式工具类

    import com ruiyun gui store haikang haikang bean FCSearchDescription import com ruiyun gui store haikang haikang bean FD
  • 【无标题】MQ静态图片获取

    public void getImageV40 String path Integer buildingProjectId HttpServletResponse response JSONObject param 61 new JSONO
  • 数据加解密时Base64异常:Illegal base64 character 3a

    现象 用base64工具类对中文进行处理时出现异常 xff0c 在数据加解密场景中经常使用 java lang IllegalArgumentException Illegal base64 character 3a at java uti
  • Winsock编程实例---TCP&UDP

    0x1 基于TCP的通信 1 服务端 1 1 创建基本流程 创建一个TCP服务端的程序需要调用的函数流程 xff1a 初始化函数库 gt gt WSAStartup 创建套接字 gt gt socket 绑定套接字 gt gt bind 监