c++网络编程

网络编程模型

    c/s 模型:客户端服务器模型b/s 模型:浏览器服务器模型

1.tcp网络流程

在这里插入图片描述
服务器流程:

    1.创建套接字2.完善服务器网络信息结构体3.绑定服务器网络信息结构体4.让服务器处于监听状态5.accept阻塞等待客户端连接信号6.收发数据7.关闭套接字

客户端流程:

    1.创建套接字2.连接connect3.收发数据4.关闭套接字

2.函数

2.1socket

#include <sys/types.h>          
#include <sys/socket.h>int socket(int domain, int type, int protocol);
功能:创建套接字参数:domain:通信域Name                                 Purpose                                                Man pageAF_UNIX,AF_LOCAL          Local communication(本地通信)          unix(7)AF_INET                             IPv4 Internet protocols                         ip(7)AF_INET6                           IPv6 Internet protocols                         ipv6(7)AF_PACKET                        原始套接字                                          packet(7)type:套接字的类型SOCK_STREAM            TCPSOCK_DGRAM              UDP使用SOCK_RAW                    原始套接字使用protocol:附加文件,没有写0返回值:成功:创建的新套接字(文件描述符)失败:-1  重置错误码

2.2bind

#include <sys/types.h>          
#include <sys/socket.h>int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
功能:绑定套接字和网络信息结构体参数:sockfd:socket函数产生的套接字文件描述符(socket函数返回值)addr:避免冲突警告

2.3listen

#include <sys/types.h>          
#include <sys/socket.h>int listen(int sockfd, int backlog);产生半连接队列功能:将套接字设置成被动监听状态,只有这个状态的套接字才能等待客户端连接参数:sockfd:socket函数返回值backlog:半连接队列的长度,一般传 5 10 都行 不是0就行返回值:成功:0失败:-1  重置错误码

accept

#include <sys/types.h>          
#include <sys/socket.h>int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);产生全连接队列,返回值创                                                                                                        建的文件描述符
功能:提取半连接队列中的第一个客户端连接,成功,放到函数产生的全连接队列中,专门             用于和当前客户端通信,返回的套接字和原套接字类型相同参数:sockfd:listen后的sockfdaddr:客户端的网络信息结构体首地址,不关心写NULLaddrlen:客户端addr长度,不关心写NULL返回值:成功:创建的新的文件描述符  专门用于和当前客户端通信失败:-1  重置错误码

connect

#include <sys/types.h>          
#include <sys/socket.h>int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);功能:与服务器建立连接 参数:sockfd:accept函数返回值addr:服务器的网络信息结构体addrlen:addr的长度返回值:成功:0失败:-1  重置错误码

服务器代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <arpa/inet.h>
#define ERRLOG(msg) do{\printf("%s %s %d\n", __FILE__, __func__, __LINE__);\perror(msg);\exit(-1);\}while(0)int main(int argc, char const *argv[])
{//1.创建套接字int sockfd=0;//需要接函数返回值,后面函数会用if(-1==(sockfd=socket(AF_INET,SOCK_STREAM,0))){ERRLOG("socket error");}//2.服务器网络信息结构体填充//struct sockaddr addr;struct sockaddr_in ad;memset(&ad, 0, sizeof(ad));ad.sin_family=AF_INET;ad.sin_port=htons(7788);//自己随意指定,不冲突就行,冲突就换ad.sin_addr.s_addr=inet_addr("192.168.250.100");//3.绑定套接字和服务器网络信息结构体if(-1==bind(sockfd,(struct sockaddr*)&ad,sizeof(ad))){ERRLOG("bind error");}//4.让套接字处于被动监听状态if(-1==listen(sockfd,5)){ERRLOG("listen error");}//5.阻塞等待客户端连接printf("正在等待客户端发来信息\n");int newfd=0;if((newfd=accept(sockfd,NULL,NULL))==-1){ERRLOG("accept error");}printf("客户端连接成功\n");//6.收发数据char buff[128]={0};int lnum=0;char opr=0;int rnum=0;int result=0;read(newfd,buff,128);printf("客户端发来数据:%s\n",buff);sscanf(buff,"%d%c%d",&lnum,&opr,&rnum);switch(opr){case '+':result=lnum+rnum;break;case '-':result=lnum-rnum;break;case '*':result=lnum*rnum;break;case '/':result=(float)lnum/(float)rnum;break;}memset(buff,0,128);sprintf(buff,"result=%d",result);write(newfd,buff,128);//7.关闭套接字close(sockfd);close(newfd);return 0;
}

客户端代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <arpa/inet.h>#define ERRLOG(msg) do{\printf("%s %s %d\n", __FILE__, __func__, __LINE__);\perror(msg);\exit(-1);\}while(0)int main(int argc, char const *argv[])
{//创建套接字int sockfd=0;if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1){ERRLOG("socket error");}//填充服务器结构体struct sockaddr_in addr;memset(&addr, 0, sizeof(addr));addr.sin_family=AF_INET;addr.sin_port=htons(6666);addr.sin_addr.s_addr=inet_addr("192.168.2.84");//连接服务器if(connect(sockfd,(struct sockaddr *)&addr,sizeof(addr))==-1){ERRLOG("connect error");}//收发数据char buff[128]={0};//写入的数据从终端获取fgets(buff,128,stdin);buff[strlen(buff)-1]='\0';write(sockfd,buff,128);memset(buff,0,128);read(sockfd,buff,128);printf("服务器发来的信息是:%s\n",buff);//7.关闭套接字close(sockfd);return 0;
}

send

#include <sys/types.h>          
#include <sys/socket.h>ssize_t send(int sockfd, const void *buf, size_t len, int flags);ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);功能:发送数据参数:sockfd:accept函数返回值buf:要发送的数据的缓冲区首地址len:要发送数据的长度flags:发送的标志位,0用法和write就一样了,MSG_DONTWAIT 表示非阻塞返回值:成功:实际发送的字节数失败:-1  重置错误码注意:如果对方关闭了套接字或者断开连接第一次send没有反应,第二次send会产生SIGPIPE信号下面三种用法是等价的:write(sockfd, buf, 128);send(sockfd, buf, 128, 0);sendto(sockfd, buf, 128, 0, NULL, NULL);

recv

#include <sys/types.h>          
#include <sys/socket.h>ssize_t recv(int sockfd, void *buf, size_t len, int flags);ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);功能:接收数据 参数:sockfd:accept函数返回值buf:要接收的数据的缓冲区首地址len:要接收数据的长度flags:发送的标志位,flags:接收的标志位,0用法和read就一样了,                                                   MSG_DONTWAIT 表示非阻塞返回值:成功:实际接收的字节数失败:-1  重置错误码注意: 如果对方关闭了套接字或者断开连接 recv 会返回0下面三种用法是等价的:read(sockfd, buf, 128);recv(sockfd, buf, 128, 0);recvfrom(sockfd, buf, 128, 0, NULL, NULL);

粘包问题产生原因

tcp在传输的时候不是一调用send就直接将数据发送给客户端的,而是将数据放到发送缓冲区里

tcp底层的nagle算法,会将一定短时间内发送的数据包组装成一个整体,发送给对方

而接受方无法区分消息的边界和类型,就可能会导致有冲突的情况发生

也就是说,当文件只剩最后一部分的时候,很有可能将最后的结束字符和文件最后一部分作为一个整体发送给接收方,也有可能将三个128和最后的30+12一起发给接收方,但不管是哪种方式,接收方写入的时候是以128为单位接受的,所以接收方缓冲区里是无法单独比较over的,所以会产生粘包问题。

解决方法:

1.既然是一定短时间内的数据成为一个整体,那么最后发送的over就不和前面一块发送了,在over之前加一个延时函数,让他单独发送

但是不常用,因为服务器里禁止使用sleep

2.发送定长的数据包,

解决方法一代码

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

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

相关文章

Appium+python自动化(二十八)- 高级滑动(超详解)

高级溜冰的滑动 滑动操作一般是两点之间的滑动&#xff0c;这种滑动在这里称其为低级的溜冰滑动&#xff1b;就是上一节给小伙伴们分享的。然而实际使用过程中用户可能要进行一些多点连续滑动操作。如九宫格滑动操作&#xff0c;连续拖动图片移动等场景。那么这种高级绚丽的溜…

【node.js】04-模块化

目录 一、什么是模块化 二、node.js中的模块化 1. node.js中模块的分类 2. 加载模块 3. node.js 中的模块作用域 4. 向外共享模块作用域中的成员 4.1 module对象 4.2 module.exports 对象 4.3 exports对象 5. node.js 中的模块化规范 一、什么是模块化 模块化是指解…

使用python库uvicorn替代Nginx发布Vue3项目

目录 一、Vue3项目打包 二、将打包文件放到python项目 三、配置uvicorn服务 四、启动服务 【SpringBoot版传送门&#xff1a;使用SpringBoot替代Nginx发布Vue3项目_苍穹之跃的博客-CSDN博客】 一、Vue3项目打包 &#xff08;博主vue版本&#xff1a;3.2.44&#xff09; 由…

Android平台GB28181设备接入侧如何同时对外输出RTSP流?

技术背景 GB28181的应用场景非常广泛&#xff0c;如公共安全、交通管理、企业安全、教育、医疗等众多领域&#xff0c;细分场景可用于如执法记录仪、智能安全帽、智能监控、智慧零售、智慧教育、远程办公、明厨亮灶、智慧交通、智慧工地、雪亮工程、平安乡村、生产运输、车载终…

2023年自然语言处理与信息检索国际会议(ECNLPIR 2023) | EI Compendex, Scopus双检索

会议简介 Brief Introduction 2023年自然语言处理与信息检索国际会议(ECNLPIR 2023) 会议时间&#xff1a;2023年9月22日-24日 召开地点&#xff1a;中国杭州 大会官网&#xff1a;ECNLPIR 2023-2023 Eurasian Conference on Natural Language Processing and Information Retr…

【Linux】进程通信 — 管道

文章目录 &#x1f4d6; 前言1. 通信背景1.1 进程通信的目的&#xff1a;1.2 管道的引入&#xff1a; 2. 匿名管道2.1 匿名管道的原理&#xff1a;2.2 匿名管道的创建&#xff1a;2.3 父子进程通信&#xff1a;2.3.1 read()阻塞等待 2.4 父进程给子进程派发任务&#xff1a;2.5…

使用adb通过电脑给安卓设备安装apk文件

最近碰到要在开发板上安装软件的问题&#xff0c;由于是开发板上的安卓系统没有解析apk文件的工具&#xff0c;所以无法通过直接打开apk文件来安装软件。因此查询各种资料后发现可以使用adb工具&#xff0c;这样一来可以在电脑上给安卓设备安装软件。 ADB 就是连接 Android 手…

NFT市场泡沫破裂了吗?投资NFT是否仍然安全?

近期&#xff0c;NFT市场的价格出现了明显的下跌趋势&#xff0c;许多人开始担心NFT市场是否已经进入了泡沫破裂的阶段。但是&#xff0c;我们需要认真分析这个问题&#xff0c;并且探讨投资NFT是否仍然安全。 NFT&#xff08;Non-Fungible Token&#xff09;是一种非同质化代币…

算法竞赛入门【码蹄集新手村600题】(MT1060-1080)

算法竞赛入门【码蹄集新手村600题】(MT1060-1080&#xff09; 目录MT1061 圆锥体的体积MT1062 圆锥体表面积MT1063 立方体的体积MT1064 立方体的表面积MT1065 长方体的表面积MT1066 射线MT1067 线段MT1068 直线切平面MT1069 圆切平面MT1070 随机数的游戏MT1071 计算表达式的值M…

网络防御之IDS

1. 什么是IDS&#xff1f; IDS是入侵检测系统&#xff0c;一种对于网络传输进行及时监视&#xff0c;在发现可疑的传输时发出警报或者采取主动反应措施的网络安全设备。IDS是一种积极地主动的防御技术。 2. IDS和防火墙有什么不同&#xff1f; 防火墙是一种隔离并过滤非授权用…

Leetcode-每日一题【剑指 Offer II 075. 数组相对排序】

题目 给定两个数组&#xff0c;arr1 和 arr2&#xff0c; arr2 中的元素各不相同 arr2 中的每个元素都出现在 arr1 中 对 arr1 中的元素进行排序&#xff0c;使 arr1 中项的相对顺序和 arr2 中的相对顺序相同。未在 arr2 中出现过的元素需要按照升序放在 arr1 的末尾。 示例&…

EtherNet/IP转CAN网关can协议标准

生产管理设备中&#xff0c;会有设备与其他设备的协议不同&#xff0c;数据无法互通&#xff0c;让你的工作陷入困境。这时&#xff0c;一款神奇的产品出现了——远创智控YC-EIP-CAN通讯网关&#xff01; 1, 这款通讯网关采用ETHERNET/IP从站功能&#xff0c;可以将各种CAN总线…

【业务功能篇58】Springboot + Spring Security 权限管理 【中篇】

4.2.3 认证 4.2.3.1 什么是认证&#xff08;Authentication&#xff09; 通俗地讲就是验证当前用户的身份&#xff0c;证明“你是你自己”&#xff08;比如&#xff1a;你每天上下班打卡&#xff0c;都需要通过指纹打卡&#xff0c;当你的指纹和系统里录入的指纹相匹配时&…

leetcode 122. 买卖股票的最佳时机 II

2023.7.29 把整体利润拆分成每天的利润&#xff0c;将股票值想象成一个折线图&#xff0c;将所有上升的值相加即可。 代码&#xff1a; class Solution { public:int maxProfit(vector<int>& prices) {int ans 0;for(int i1; i<prices.size(); i){if(prices[i]-…

SpringBoot使用jetty和tomcat还有undertow以及ssl配置支持https请求

一般使用SpringBoot开发应用程序都是使用的tomcat 稍微注意点性能就使用undertow&#xff0c;配置支持https请求常用nginx来做代理&#xff0c;直接用SpringBoot配置还是很少的&#xff0c;八成用不到&#xff0c;就怕需要用到的时候又不能及时弄出来&#xff0c;于是记录一下。…

CenOS设置启动级别

背景知识 init一共分为7个级别&#xff0c;这7个级别的所代表的含义如下 0&#xff1a;停机或者关机&#xff08;千万不能将initdefault设置为0&#xff09;1&#xff1a;单用户模式&#xff0c;只root用户进行维护2&#xff1a;多用户模式&#xff0c;不能使用NFS(Net File S…

第2集丨webpack 江湖 —— 创建一个简单的webpack工程demo

目录 一、创建webpack工程1.1 新建 webpack工程目录1.2 项目初始化1.3 新建src目录和文件1.4 安装jQuery1.5 安装webpack1.6 配置webpack1.6.1 创建配置文件&#xff1a;webpack.config.js1.6.2 配置dev脚本1.7 运行dev脚本 1.8 查看效果1.9 附件1.9.1 package.json1.9.2 webpa…

ReactRouterv5在BrowserRouter和HashRouter模式下对location.state的支持

结论&#xff1a;HashRouter不支持location.state 文档&#xff1a;ReactRouter v5 从文档可看到history.push()方法支持2个参数&#xff1a;path, [state] state即是location.state&#xff0c;常用于隐式地传递状态参数 但文档未提的是&#xff0c;仅适用于BrowserRouter&am…

《面试1v1》Kafka的架构设计是什么样子

&#x1f345; 作者简介&#xff1a;王哥&#xff0c;CSDN2022博客总榜Top100&#x1f3c6;、博客专家&#x1f4aa; &#x1f345; 技术交流&#xff1a;定期更新Java硬核干货&#xff0c;不定期送书活动 &#x1f345; 王哥多年工作总结&#xff1a;Java学习路线总结&#xf…

百度开发者平台API地理编码,根据地址获取经纬度

地理编码 | 百度地图API SDK (baidu.com) 原始csv # encoding:utf-8 import requests import csv import json # 接口地址 url "https://api.map.baidu.com/geocoding/v3"# 此处填写你在控制台-应用管理-创建应用后获取的AK ak "XXXXXXX"# 创建CSV文件并…