c++网络编程

2023-10-27

网络编程模型

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

    b/s 模型:浏览器服务器模型

1.tcp网络流程

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

    1.创建套接字

    2.完善服务器网络信息结构体

    3.绑定服务器网络信息结构体

    4.让服务器处于监听状态

    5.accept阻塞等待客户端连接信号

    6.收发数据

    7.关闭套接字

客户端流程:

    1.创建套接字

    2.连接connect

    3.收发数据

    4.关闭套接字

2.函数

2.1socket

#include <sys/types.h>          
#include <sys/socket.h>

int socket(int domain, int type, int protocol);
功能:创建套接字

参数:domain:通信域

                    Name                                 Purpose                                                Man page
                    AF_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            TCP

                        SOCK_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后的sockfd

           addr:客户端的网络信息结构体首地址,不关心写NULL

           addrlen:客户端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.发送定长的数据包,

解决方法一代码

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

c++网络编程 的相关文章

  • 使用PHP从doc、xls文件中读取数据

    我想知道是否可以从 doc 和 xls 文件中读取数据并将 将内容读取到图像文件中 创建文档的页面样本 例如 我有一些文件希望我的客户购买 所以我需要自动创建小图像 例如我的文档样本 我们将不胜感激您的帮助 对于读取 xls 文件 我真的推
  • php - 解析html页面

    div divbox div p para1 p p para2 p p para3 p table class table tr td td tr table p para4 p p para5 p 有人可以告诉我如何解析这个 html
  • 在 Windows 窗体中保存带有 Alpha 通道的单色位图会保存不同(错误)的颜色

    在 C NET 2 0 Windows 窗体 Visual Studio Express 2010 中 我保存由相同颜色组成的图像 Bitmap bitmap new Bitmap width height PixelFormat Form
  • HTTPWebResponse 响应字符串被截断

    应用程序正在与 REST 服务通信 Fiddler 显示作为 Apps 响应传入的完整良好 XML 响应 该应用程序位于法属波利尼西亚 在新西兰也有一个相同的副本 因此主要嫌疑人似乎在编码 但我们已经检查过 但空手而归 查看流读取器的输出字
  • C# 中通过 Process.Kill() 终止的进程的退出代码

    如果在我的 C 应用程序中 我正在创建一个可以正常终止或开始行为异常的子进程 在这种情况下 我通过调用 Process Kill 来终止它 但是 我想知道该进程是否已退出通常情况下 我知道我可以获得终止进程的错误代码 但是正常的退出代码是什
  • 使用 WebClient 时出现 System.Net.WebException:无法创建 SSL/TLS 安全通道

    当我执行以下代码时 System Net ServicePointManager ServerCertificateValidationCallback sender certificate chain errors gt return t
  • 雄辩的第一个 where 子句

    我想知道 Laravel 如何实现雄辩的语法 以便可以静态调用第一个 where 子句User where User where id 23 gt where email email gt first 他们有吗public static f
  • PHP session_regenerate_id 和黑莓浏览器

    问候 我正在开发一个登录系统 并陷入了黑莓浏览器身份验证的困境 他们似乎对 PHP 的 session regenerate id 有问题 有人可以建议替代方案吗 以下是身份验证和登录脚本 UPDATE看来会话一般都不起作用 拿出 sess
  • 如何在整个 ASP .NET MVC 应用程序中需要授权

    我创建的应用程序中 除了启用登录的操作之外的每个操作都应该超出未登录用户的限制 我应该添加 Authorize 每个班级标题前的注释 像这儿 namespace WebApplication2 Controllers Authorize p
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • 什么时候虚拟继承是一个好的设计? [复制]

    这个问题在这里已经有答案了 EDIT3 请务必在回答之前清楚地了解我要问的内容 有 EDIT2 和很多评论 有 或曾经 有很多答案清楚地表明了对问题的误解 我知道这也是我的错 对此感到抱歉 嗨 我查看了有关虚拟继承的问题 class B p
  • 在本地 SDK 服务器上工作时,实时 Google App Engine 上出现 404

    我已经在GAE标准环境上部署了几个PHP应用程序 一切正常 现在我正在部署一个新应用程序 该应用程序位于由gcloudSDK按预期工作 终端命令 dev appserver py log level warning app yaml 问题是
  • 使用 x509 证书签署 json 文档或字符串

    如何使用 x509 证书签署 json 文档或字符串 public static void fund string filePath C Users VIKAS Desktop Data xml Read the file XmlDocum
  • 矩形超出边界是什么意思

    PPB Graphics2D PaintImageData 矩形超出界限是什么意思 我几乎在我检查的每一段代码中都看到了它 最新的代码是 define my consumer key define my consumer secret oa
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • 链接器错误:已定义

    我尝试在 Microsoft Visual Studio 2012 中编译我的 Visual C 项目 使用 MFC 但出现以下错误 error LNK2005 void cdecl operator new unsigned int 2
  • 通过指向其基址的指针删除 POD 对象是否安全?

    事实上 我正在考虑那些微不足道的可破坏物体 而不仅仅是POD http en wikipedia org wiki Plain old data structure 我不确定 POD 是否可以有基类 当我读到这个解释时is triviall
  • 基于 OpenCV 边缘的物体检测 C++

    我有一个应用程序 我必须检测场景中某些项目的存在 这些项目可以旋转并稍微缩放 更大或更小 我尝试过使用关键点检测器 但它们不够快且不够准确 因此 我决定首先使用 Canny 或更快的边缘检测算法 检测模板和搜索区域中的边缘 然后匹配边缘以查
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags

随机推荐

  • MySQL8.0连接问题总结

    MySQL8 0连接问题总结 1 驱动包版本 2 驱动类 3 连接属性 1 驱动包版本 对于8 0版本的MySQL数据库 驱动包版本也要跟上 一般使用mysql connector java 8 0 11 否则会报如下错误 Caused b
  • vue代码片段

    Place your snippets for vue here Each snippet is defined under a snippet name and has a prefix body and description The
  • new Object() 和Object.create(null)

    new Object 和Object create null const obj1 a 10 b 20 const obj2 a 10 b 20 obj1 obj2 gt gt gt false 引用类型 因为内存地址不同 const ob
  • Spring之ApplicationContext快速入门

    目录 一 概述 二 代码演示 三 BeanFactory与ApplicationContext的关系 四 BeanFactory的继承体系 五 ApplicationContext的继承体系 一 概述 ApplicationContext称
  • mfc 程序闪退_VC6 在Window10 上操作打开文件时闪退或直接退出的解决方法

    1 下载FileTool exe 并解压 2 打开VC6 0 点击File Open Workspace 选择刚解压出来的FileTool dsw 并确定 3 点击Bulid Build FileTool dll 生成FileTool dl
  • 编程求1平方+2平方+...+n平方

    题目描述 编程求1平方 2平方 n平方 输入 输入一行 只有一个整数n 1 lt n lt 200 输出 输出只有一行 这意味着末尾有一个回车符号 包括1个整数 样例 输入 5 输出 55 提示 循环语句 include
  • 浅谈Visitor访问者模式

    一 前言 什么叫访问 如果大家学过数据结构 对于这点就很清晰了 遍历就是访问的一般形式 单独读取一个元素进行相应的处理也叫作访问 读取到想要查看的内容 对其进行处理就叫作访问 那么我们平常是怎么访问的呢 基本上就是直接拿着需要访问的地址来读
  • [USACO Open08]农场周围的道路

    题目描述 约翰的 N 1 N 10 9 只奶牛要出发去探索牧场四周的土地 她们将沿着一条路走 一直走到三岔路口 可以认为所有的路口都是这样的 这时候 这一群奶牛可能会分成两群 分别沿着接下来的两条路继续走 如果她们再次走到三岔路口 那么仍有
  • linux ./ 执行run文件,如何在Ubuntu中执行.bin和.run文件

    在解释如何在Ubuntu上执行 bin和 run文件之前 让我们首先定义这些文件扩展名到底是什么 Bin档 Ubuntu中的Binary或BIN文件指的是安装软件包 其中大多数是self extracting可执行文件 用于在系统上安装软件
  • BF算法 KMP算法

    BF算法 又叫朴素算法 时间复杂度为O mn 相比KMP算法比较简单 举个例子 对于给定的主字符串 ababbcabcdabcde 和子串 abcd 我们用i和j来分别遍历两个字符串 比较两个i j 对应字符串位置的元素是否相等 如果相等则
  • 应用软件的层次划分

    谈到应用程序的层次 我们平时所说的层次有两种 逻辑的层次 layer 和部署的层次 tier 这两种层次划分的目的是不同的 因此划分方式也有一些差异 能够为应用程序带来的好处也是不同的 逻辑层次逻辑层次 layer 划分的最重要的目的在于调
  • JavaScript设计模式(五)——发布订阅模式、桥接模式、组合模式

    个人简介 个人主页 前端杂货铺 学习方向 主攻前端方向 正逐渐往全干发展 个人状态 研发工程师 现效力于中国工业软件事业 人生格言 积跬步至千里 积小流成江海 推荐学习 前端面试宝典 Vue2 Vue3 Vue2 3项目实战 Node js
  • java父类_java 子类与父类

    子类是由继承得到的类 被继承的类就是父类 子类与父类是 is a 关系 一 子类与父类 1 子类 1 子类定义 class 子类名 extends 父类名 2 子类继承性 子类继承了父类的所有属性和除了构造方法的其余方法 子类与父类在同个包
  • Python实现保留三位有效数字

    网上查找了较多的四舍五入的方法 发现不是自己想要的 于是自己按数目级别写了一段 后面又做了更改 做了简单的整合 整体思路就是取第三位数作判断 如果是第三位是5 再判断第四位的奇偶性 作为小白 代码整体逻辑比较呆板 希望有大神做下修改 定义保
  • ssm框架ajax登录页面,ssm框架登录注册demo

    实例简介 ssm框架登录注册demo html页面 ajax实现登录注册 实例截图 核心代码 ssm ssm pom xml src main java controller TestController java UserControll
  • 海思(MPP)媒体处理软件平台(1)-----功能简介

    概述 HI3531D 海思提供的媒体处理软件平台 Media Process Platform 简称 MPP 可支持应用软件快速 开发 该平台对应用软件屏蔽了芯片相关的复杂的底层处理 并对应用软件直接提供 MPI MPP Programe
  • React渲染顺序及useEffect执行顺序探究(含并发模式)

    前言 在不借助任何演示的情况下 你能清楚地说出 React 组件的渲染顺序以及 useEffect 的执行顺序吗 你知道 React18 并发模式 下执行情况是不同的吗 下面就让我们一起来看一看吧 React 16 先来看目前大部分人还在用
  • 【C语言】强符号和弱符号

    1 强符号 弱符号定义 编译器在编译源程序时 无论你是变量名 函数名 在它眼里 都是一个符号而已 用来表征一个地址 编译器会将这些符号集中 存放到一个叫符号表的 section 中 那么对于两个 c文件中存在的同名的变量 编译器该怎么选择呢
  • 切换零感知 H3C H5家庭智慧无线套装牛在哪?

    我头上有犄角 我身后有尾巴 大家看到这句歌词首先想到的是 小青龙 而小编认为这是对传统无线路由器最为真实的写照 犄角 就是无线路由器的外置天线 尾巴 也就是无线路由器的电源线以及连接各个端口的网络线路 随着大家审美的变化 无线路由器这种最为
  • c++网络编程

    网络编程模型 c s 模型 客户端服务器模型 b s 模型 浏览器服务器模型 1 tcp网络流程 服务器流程 1 创建套接字 2 完善服务器网络信息结构体 3 绑定服务器网络信息结构体 4 让服务器处于监听状态 5 accept阻塞等待客户