C/C++:WinSock_TCP通信实例

news2025/1/16 0:51:38

一、socket函数

第一种使用socket函数来创建套接字,函数调用成功将返回套接字句柄。

 

socket函数接收三个参数。af 、type 、protocol 

        af:指定套接字使用的地址格式。

        type:指定套接字的类型。

        protocol:配合type参数使用,用来指定使用的协议类型。

函数执行失败返回INVALID_SOCKET(即-1),可以通过WSAGetLastError函数取得错误代码。

        当不使用套接字时,应使用把它关闭,如果不发生错误,函数返回0,发生错误函数返回SOCKET_ERROT。

int closesocket(SOCKET s);

1.AF地址族

AF地址族在ws2def.h头文件里定义。

地址族名称解释
AF_UNSPEC  地址族未指定。
AF_INET  Internet协议版本4(IPv4)地址族。

2.TYPE套接字类型

        套接字类型一共有三种,分别是SOCK_STREAM流式套接字SOCK_DGRAM数据包套接字,SOCK_RAW原始套接字。

类型解释
SOCK_STREAM使用TCP进行提供有连接的可靠传输
SOCK_DGRAM使用UDP提供无连接的不可靠传输
SOCK_RAW不使用特定的协议去封装,靠程序自行处理数据以及协议

 3.PROTOCOL

        用于指定通信协议类型,在ws2def.h头文件里被定义。

 当type已经明确指定使用TCPUDP进行工作的时候,protocol参数可以指定为0.

二、套接字绑定到本地IP和端口

        使用bind函数为套接字建立连接,能够将套接字句柄(套接字文件描述符)、端口号和本地ip绑定到一起。

int bind(
    SOCKET s,
    const struct sockaddr* name,
    int namelen
);

 bind函数接收三个参数。s 、name 、namelen 

        s:套接字句柄

        name:本地地址

        namelen:name结构体的大小。

函数调用成功则返回0 ,失败返回-1,错误原因存于 errno 中,可以通过WSAGetLastError函数取得错误代码。如果绑定的地址错误,或者端口已被占用,bind 函数一定会报错。

 1.SOCKADDR本地地址结构体

        Winsock的第一个版本使用sockaddr结构来解决多种协议地址添加的问题,以下是其结构体结构。

typedef struct sockaddr {
    ADDRESS_FAMILY sa_family;           // Address family.
    CHAR sa_data[14];                   // Up to 14 bytes of direct address.
} SOCKADDR, *PSOCKADDR, FAR *LPSOCKADDR;

        该结构体的第一个成员sa_family指定了这个地址使用的AF地址族sa_ data是个杂糅数组存储的数据在不同的地址家族可能不同。所以Winsock对于TCP/IP使用sockaddr_in结构来存储,最后通过强制转换成sockaddr来使用。

 2.SOCKADDR_IN TCP/IP地址结构体

        该结构体专门用来TCP/IP版本的sockaddr的结构体,其结构体结构如下:

typedef struct sockaddr_in {
    ADDRESS_FAMILY sin_family;
    USHORT sin_port;
    STRUCT IN_ADDR sin_addr;
    CHAR sin_zero[8];
} SOCKADDR_IN, *PSOCKADDR_IN;

该结构体有四个成员,分别如下:

        sin_family:AF地址族,应为AF_INET。

        sin_port:端口号,需要用htons(unsigned short)函数转换。

        sin_addr:指定IP地址,需要使用inet_addr()函数进行字符串转换。

        sin_zero[8]:空字节,要设为0,用于让其结构与sockaddr结构相同,方便强制转换。

案例:指定端口号代码

sockaddr_in servAddr;
servAddr.sin_port = htons(4567);

案例:指定 IP地址代码

sockaddr_in servAddr;
servAddr.sin_addr.S_un.S_addr = inet_addr("26.186.41.134");

 这里只是简单说明一下代码,具体的原理,以及结构体结构会详细说明。

三、监听套接字

        WinSock主要使用listen函数进行监听对应套接字,是否有连接等操作,该函数仅应用在支持连接的套接字上。

int listen(
  SOCKET s,
  int backlog  
);

        函数的参数有两个,其一是SOCKET设置需要监听的套接字,其二是backlog设置监听队列中允许保持的尚未处理的最大连接数量。如果一个连接请求到来,但队列中的连接的等待数量超过backlog,则客户端将收到WSAECONNREREFUSED的错误。

四、接收连接请求

1.accept()函数

WinSock服务端主要使用accept函数来接收到服务器来的socket连接。

函数原型如下: 

SOCKET accept(
   SOCKET s,
   struct sockaddr* addr,
   int* addrlen
);

        该函数有三个参数,其一是SOCKET代表listen函数监听的套接字,在其队列中指出第一个到来的未处理套接字连接,并为其创造新的套接字。其二是addr一个指向sockaddr结构的指针,用来取得连接的地址信息。其三是指向参数二长度的指针

 2.connect()函数

WinSock客户端主要使用connect函数来连接到服务器。

 函数原型如下: 

int connect(
    SOCKET s,
    struct sockaddr FAR * name,
    int namelen
);

         该函数有三个参数,其一是SOCKET代表连接服务器使用的客户端套接字。其二是addr一个指向sockaddr结构的指针,用来取得连接的地址信息。其三是指向参数二长度的指针

五、收发数据

对于流套接字来说,一般使用send()函数发数据,recv函数收数据,二者函数结构很相似。

1.send()函数

主要用于流套接字发送数据。

函数原型如下

int send(
    SOCKET s,
    char *buf,
    int len,
    int flags
);

       该函数有四个参数,其一是SOCKET代表一个连接的套接字。其二是buf一个字符数组代表发送数据缓存区其三是len代表缓存区长度其四flags值通常指定为0

2.recv()函数

主要用于流套接字接收数据。 

函数原型如下 

int recv(
    SOCKET s,
    char* buf,
    int len,
    int flags
);

        该函数有四个参数,其一是SOCKET代表一个连接的套接字。其二是buf一个字符数组代表接收数据缓存区其三是len代表缓存区长度其四flags值通常指定为0

六、TCP服务端和客户端程序通信实例

WinSock编程首先要做的必须是初始化Winsock库,这样才能开始编程使用库里的函数。

关于初始化WinSock库参考博客: 

1.服务端

流程思路讲解:

        创建一个套接字sListen用于监听,再将套接字绑定到服务器的本地地址(一张网卡地址上 或者 值为INADDR_ANY,相当于0.0.0.0,表示任意地址),然后使用listen监听函数,监听套接字,接着调用accept函数循环接收客户请求,并创建一个新的套接字Socket,服务端接收请求后使用recv函数和send函数收发数据。完成数据交换后,关闭套接字Socket,继续等待新的连接。服务器关闭后使用::closesocket()关闭监听套接字。

2.客户端

流程思路讲解:

        创建一个套接字socket用于连接,再将套接字绑定到客户端的本地地址(一张网卡地址上),然后使用connect函数,连接服务器。连接成功后,使用recv函数和send函数收发数据。完成数据交换后,关闭套接字Socket。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Appium中的api(二)

目录 元素定位操作api 1--通过id定位api 2--通过class获取定位元素 3--通过xpath表达式定位元素 4.完整代码 解释 效果 元素定位操作api 1--通过id定位api 注:driver.find_element是获取单个元素 # 通过id获取 mySearchId "com.android.settings:id/search_acti…

(2024.10.28)使用YOLOv8训练自己的目标检测模型

收集数据集: 1.使用开源已标记数据集 2.自己网上搜索下载。 3.可以将图片几何变换,类似翻转、裁剪、旋转和平移,就变成多张图片了 标注数据集 : 常用的标注工具有很多,比如LabelImg(易崩溃)…

nacos的原理,为什么可以作为注册中心,和zookeeper的区别

Nacos 是阿里巴巴开源的一款用于动态服务发现、配置管理和服务治理的中间件,广泛应用于微服务架构中。它可以作为注册中心的原因在于其强大的服务注册与发现功能,原理上与 Zookeeper 有相似之处,但在设计目标和功能上有所区别。 Nacos 的原理…

猫头虎分享: 108个最新国内AI工具集,AI写作AI绘画工具大全

猫头虎分享: 108个最新国内AI工具集,AI写作AI绘画工具大全 🎨🤖 👋 大家好呀,这里是 猫头虎,专注于分享技术干货、AI工具和实用资源。今天给大家带来一份超级干货清单——108个国内最流行的AI工…

PPT制作新选择:本地部署PPTist结合内网穿透实现实时协作和远程使用

文章目录 前言1. 本地安装PPTist2. PPTist 使用介绍3. 安装Cpolar内网穿透4. 配置公网地址5. 配置固定公网地址 💡 推荐 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【点击跳转到网站】 前…

【Python】数据分析必备:Pandas库的全面教程与实战

数据分析必备:Pandas库的全面教程与实战 在数据分析领域,Python已成为一门主流语言,而Pandas库则是Python中最重要的数据分析工具之一。无论是数据清洗、数据处理,还是数据可视化,Pandas都能为数据科学家和分析师提供…

解决nexus无法启动问题

🎉 问题 首先,nexus对jdk版本有要求,这点相信大家都知道,如果版本不对的话,会报以下错误: No suitable Java Virtual Machine could be found on your system. The version of the JVM must be at least 1…

ZEISS ATOS Q蓝光三维扫描仪高效把控零件质量检测【上海沪敖3D】

位于Bengaluru的施耐德电气工厂拥有一流的计量设备,可以检测所有供应商的零件。当时,他们在使用一款激光扫描设备进行质量检测,但是,该设备不便于携带,且检测时需要喷涂大量的显影液。此外,它需要被安装在夹…

React中的hook

React中的hook究竟是什么? 有哪些hook? hook的两大规则 为什么hook要在顶层调用? hook的调用需要在每一次render后都按照一样的顺序进行调用,否则会出现类似“野指针”的情况,但是要做到这一步,就需要hook在…

微服务网格Istio介绍

微服务网格Istio 介绍服务注册和发现服务度量灰度发布 Istio核心特性断路器互动1:举个生活中的例子解释断路器互动2:服务降级(提高用户体验效果) 超时重试多路由规则 Istio架构istio组件详解PilotEnvoyCitadelGalleyIngressgatewa…

Spring Cloud --- Sentinel 热点规则

何为热点 热点即经常访问的数据,很多时候我们希望统计或者限制某个热点数据中访问频次最高的TopN数据,并对其访问进行限流或者其它操作 热点规则 方法 testHotKey 里面第一个参数 P1 只要 QPS 超过每秒 1 次,马上降级处理 请求路径中不管…

ArcGIS 10.8 安装教程(含安装包)

目录 一、ArcGIS10.8二、安装链接三、安装教程四、ArcGIS实战 (一)ArcGIS10.8 1. 概述 ArcGIS 10.8是由美国Esri公司开发的GIS平台,用于处理、分析、显示和管理地理数据,并实现数据共享。它具有新特性和功能,性能更…

信号完整性SI总结【小登培训】

信号完整性问题的根源通常在于阻抗不匹配、串扰、时序误差、电磁辐射和电源噪声。解决这些问题需要从PCB设计、布线、材料选择、匹配和屏蔽等多个方面综合考虑,并结合眼图分析等工具进行调试和优化。确保信号完整性对于高速电路设计尤为重要,影响系统的可…

异常处理与调试:如何编写稳健的代码(8/10)

目录 异常处理与调试:如何编写稳健的代码(8/10) 介绍 异常概述 常见的异常类型 使用 try...except 处理异常 基本结构 示例:读取文件内容 捕获多个异常 自定义异常 示例:自定义异常类 调试代码 使用 print…

智能融合:国际数字影像产业园的数字化转型之路践

国际数字影像产业园作为数字园区的典型代表,在现代城市与企业发展进程中扮演着至关重要的角色。它深度融合了信息技术、物联网、大数据等一系列先进技术,全力聚焦于提升城市及企业的智能化水准与管理效能。 产业园围绕数字影像这一特定主题,…

基于KV260的基础视频链路通路(MIPI+Demosaic+VDMA)

目录 1. 简介 1.1 要点 1.2 背景 1.2.1 Got stuck 1.2.2 Cant be Initialized 2. Overlay 2.1 参考 Overlay 2.1.1 KV260 Base 2.1.2 Pynq-CV-OV5640 2.2 自建 Overlay 2.2.1 IIC IP 2.2.2 MIPI CSI-2 Rx 2.2.3 AXI4-S Subset 2.2.4 Demosaic 2.2.5 Pixel Pack …

【MySQL 保姆级教学】内置函数(9)

内置函数 1. 日期函数1.1 日期函数的种类1.2 示例1.3 日期的转换 2. 字符串函数2.1 种类2.2 示例 3. 数学函数3.1 种类3.2 向上取整和向下取整3.3 示例 4. 其他函数4.1 查询当前用户/数据库4.2 ifnull(val1,val2)4.3 md5()函数4.4 password()函数 1. 日期函数 1.1 日期函数的种…

Python | Leetcode Python题解之第514题自由之路

题目: 题解: Test "godding" target "d"i 0left i lc 0 right i rc 0while Test[left] ! target:left - 1lc 1if left -1:left len(Test) - 1while Test[right] ! target:right 1rc 1if right len(Test):right 0prin…

我用自研引擎做游戏:《干得好,托尼》

最近心里突然有个想法,想做一个游戏试试看。但是我从未做过游戏,这可咋办?我理性的思考了片刻,清楚的意识到,我要习得做游戏的方法论。于是到网上找了几本开发游戏的电子书,看了几天,就开始进入…

滚珠花键精密结构如何驱动旋转运动?

滚珠花键作为一种机械传动装置,具有升降旋转机构的功能,被广泛应用于各种机器设备中。那么,大家知道滚珠花键是如何实现旋转运动的吗? 滚珠花键实现旋转运动的工作原理可以概括为滚动摩擦和轴向移动与径向传动这两点,当…