手机上的APP是如何与服务器通信的

文章转自本人公众号:机械猿,本人之前在四川某汽轮机从事结构强度设计,目前在阿里巴巴淘宝事业部担任高级开发工程师,有机械工程同行想转行IT,或者有想入职BAT的可以找我内推~

絮叨

       讲解CS通信之前,先大致了解一下我们平时手机通话的流程。语音信号经过脉冲采样变成数字信号,通过手机GSM模块发送无线信号至基站进入无线接入网,根据对方手机号查询数据库后通过骨干路由器转入核心网,一连串中转之后发送到对端所属的小区,找一条空闲线路接通对方。

       网络通信类似,但是也有不同,电话信号只能维持一条连接,而一个服务端可以维持多条连接,像双十一淘宝OceanBase就达到了一千万QPS的并发量。

这里实名给手淘打个招聘广告

基础知识

了解APP通信首先要了解socket的含义。Socket是一种进程通信方式,可用于多主机之间的通信,IP地址(对应主机)和端口(对应进程)就确定了一个socket,类似于电话的插座。下面我们来实现一个基础网络示例:客户端从标准输入读取文本,发送给服务器;服务器接收后原文返回给客户端,客户端输出到标准输出。

注:标准输入STDIN位于 /dev/stdin ,一般为键盘输入,fd为0;标准输出STDOUT位于/dev/stdout,一般为终端显示器,fd为1;标准错误 STDERR位于/dev/stderr,fd为2。

       TCP客户/服务端程序基本流程如下:

服务端处理流程

服务端程序如下:

#include<sys/socket.h>     /* basic socket definitions */
int main(int argc, char **argv)
{int listenfd,connfd;pid_t childpid;socklen_t clilen;struct sockaddr_incliaddr, servaddr;listenfd = Socket(AF_INET, SOCK_STREAM,0);  //创建套接字,监听端口bzero(&servaddr, sizeof(servaddr));servaddr.sin_family      = AF_INET;servaddr.sin_addr.s_addr =htonl(INADDR_ANY);servaddr.sin_port        = htons(SERV_PORT);Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));  //绑定本机地址Listen(listenfd, LISTENQ);      //监听for ( ; ; ) {clilen = sizeof(cliaddr);connfd = Accept(listenfd, (structsockaddr *) &cliaddr, &clilen);  //阻塞等待客户端SYN报文if ( (childpid = Fork()) == 0) {      /* fork一个子进程专门处理接入的客户端 */Close(listenfd);            /* 子进程关闭监听端口 */str_echo(connfd);       /* 子进程发送请求 */exit(0);}Close(connfd);                    /* 父进程关闭连接端口 */}
}

下面分析一下服务端状态机流程:

服务端创建一个监听套接字并绑定本机知名端口(如80、8080http端口),本机地址设置为INADDR_ANY是为了任何本地接口的连接都接收,一般为多网卡的场景。之后服务端阻塞在accpt调用,使用fork为每个客户端专门分配一个子进程,父进程继续监听接入的客户端。

对于已连接的客户端,使用str_echo读入客户端发送过来的数据,并直接返回回去。

void str_echo(intsockfd)
{ssize_t n;char buf[MAXLINE];again:while ( (n = read(sockfd, buf, MAXLINE))> 0)   //从标准输入读取数据Writen(sockfd, buf, n);        //发送至服务端// while循环退出说明接收到FIN包,客户端完成了数据发送if (n < 0 && errno == EINTR)goto again;                    //被信号打断,继续读取else if (n < 0)err_sys("str_echo: readerror");   //遇到其他错误结束运行
}

客户端处理流程

下面给出客户端处理状态机(省略部分socket异常处理):

str_cli处理逻辑如下:

void str_cli(FILE* fp, int sockfd)
{charsendline[MAXLINE],recvline[MAXLINE];while (fgets(sendline, MAXLINE, fp) !=NULL) {  //从fp读入数据Writen(sockfd, sendline,strlen(sendline));  //发送给服务器if (Readline(sockfd, recvline,MAXLINE) == 0)   //接收服务器发送过来的数据err_quit("str_cli:server terminated prematurely");  //如果为0,说明服务端已关闭连接fputs(recvline, stdout);  //将接收到的数据输出到终端}   //文件读取结束时fgets返回NULL,while退出
}

运行客户端/服务端程序

服务器启动后,在客户端连接之前,使用netstat -a检查主机监听套接字状态如下:

Proto   Local Address       Foreign Address       State
TCP     *:9877               *:*                LISTEN

来启动客户端并指定服务器地址127.0.0.1(本地环回地址),客户端在connect函数中完成TCP三次握手流程,之后服务端从accept中返回,一条数据通道建立。

服务端这边握手流程较为复杂,用简图表示如下:

连接建立后,客户端阻塞于fgets等待接收键盘输入,服务端进程从accept返回后调用fork创建一个子进程专门负责这条连接,父进程继续阻塞在accept上监听新客户端的到来。此时,三个进程都阻塞:客户端进程、服务器父进程、服务器子进程。

注1:一个程序不等于一个进程,像淘宝,除了主进程进行各种数据处理外,还有push进程作为维持客户端和服务器的长连接通信,用于发送心跳包和推送消息。

注2:建立连接时,客户端阻塞在connect上,收到服务器的SYN/ACK报文即返回,而服务器需要收到ACK报文才返回,两边阻塞时间差了半个RTT。

使用netstat -a观察现在连接情况:​​​​​​​

Proto    Local Address           Foreign Address            StateTCP     localhost:9877           localhost:47512             ESTABLISHED //服务器TCP     localhost:47512          localhost:9877              ESTABLISHED    //客户端TCP     *:9877                   *:*                         LISTEN  //服务器父进程可以看到双方socket已处于ESTABLISHED状态,接下来客户端可以和服务器进行数据收发。当客户端输入EOF字符(按下Control+Z表示终止输入)时,fgets返回空指针,客户端数据处理函数str_cli返回,客户端main函数调用exit终止进程。进程终止会关闭所有打开的文件描述符,因此客户端会发送FIN报文给服务器,服务器子进程回应ACK后也调用exit函数关闭文件描述符,发送FIN报文。

这里除了通过TCP四次挥手正常终止连接,还可以发送信号kill -9 pid终止进程。信号的处理后续剖析~

上述程序对服务器主机崩溃、主机重启、主机关机及客户端主机崩溃等异常情况都做了保护,这也是我们平时写需要注意程序健壮性的地方。

最后厚着脸皮推广一下自己的公众号:机械猿,有机械工程同行想转行IT,或者有想入职BAT的可以找我内推~

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

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

相关文章

美区google play礼品卡,如何正确充值到美区google play余额,并能购买游戏道具

前提1&#xff0c;打开网页&#xff1a; www.ip.cn 查询您所在IP地区&#xff0c;如果显示美国&#xff0c;就可以操作第二步了。如果非美国请更换。必须显示美国才能操作第二步2&#xff0c;打开付款资料查询地址 &#xff1a; https://pay.google.com/payments/u/8/home#set…

chatgpt赋能Python-python_ico

Python ICO简介 Python ICO是利用Python编写智能合约的一种通用格式。ICO的全称为Initial Coin Offering&#xff08;首次代币发行&#xff09;&#xff0c;是一种类似于股票发行的融资方式&#xff0c;通过区块链技术发行代币&#xff0c;吸引投资者购买来支持项目的发展。 …

【ChatGPT提问技巧和各种资源帮找】

ChatGPT提问技巧和各种资源帮找 ChatGPT提问技巧 为了防止迷路&#xff0c;文件放在了网盘&#xff0c;连接如下&#xff1a;https://pan.quark.cn/s/e2b8266c789a 资源帮找 整理了各种资源合集&#xff0c;大家有需要的可以留言&#xff0c;包括但不限于《电子书》、《教育…

ChatGLM-6B详细学习实践记录与资料分享

随着年初chatGPT产品的退出和迭代发展&#xff0c;凭借一己之力将大模型带火&#xff0c;国产很多厂商后续也陆续跟进开始投入研发属于自己的大模型产品&#xff0c;在这段时间里面陆陆续续出来了很多不同的产品&#xff0c;比如&#xff1a;文心一言、星火大模型、通义千问、商…

RISC-V给异构计算带来新活力

来源: EEWORLD ChatGPT的火热&#xff0c;持续催生着包括人工智能、大数据等应用的火热。在不断兴起的新应用的背后&#xff0c;需要更复杂的计算方式&#xff0c;而异构计算概念也因此诞生。将不同的计算任务进行分解&#xff0c;利用包括GPU、CPU、NPU等不同的架构及指令集处…

chatgpt赋能python:Python字符串截断-解决方式及实现方法

Python字符串截断-解决方式及实现方法 在Python编程中&#xff0c;处理字符串是一个非常常见的任务。其中&#xff0c;字符串截断也是在许多场景下必不可少的功能之一。Python不仅提供了许多内置函数来处理字符串&#xff0c;而且还有许多方法来截断字符串。 什么是字符串截断…

《知识变现》

为什么你的知识不能变现&#xff1f; 博客中添加了书写人生一个栏目,回顾过去曾经读过的好书,以及自己的感悟. 今天推举的一本书是来自萧秋水/剽悍一只猫(笔名) 联合写的. 一看标题, 该书是如何将教人走上自由职业知识变现的道路. 如何成为一个斜杠青年. 作者背景 萧秋水: …

给软件测试加满ChatGPT Buff

各位测试小伙伴大家好呀~自从ChatGPT问世&#xff0c;有关它的讨论可谓是铺天盖地&#xff0c;国内的类GPT大模型如文心一言、通义千问等也开始内测&#xff0c;AI俨然成为了热门话题。 根据现在的新闻报道&#xff0c;ChatGPT 4已经可以自己写代码&#xff0c;甚至比得上谷歌…

思腾合力「IW2211-4GR/2GR」专业双路机架式服务器

随着5G时代到来&#xff0c;数字技术与实体经济相融合&#xff0c;人工智能技术迅速发展。 伴随大数据时代的到来&#xff0c;实时、大量、多来源的数据纷纷涌现。云计算通过将大数据挖掘的海量数据进行存储和计算&#xff0c;让数据发挥最大的作用。 大数据和云计算为人工智能…

海思hi3531d音频外接codec (tlv320aic32x4)

前言 为了在海思平台上使用tlv320aic3254&#xff0c;花了大概2个星期研究海思音频部分的手册、3254的用户手册&#xff0c;最终参考tlv320aic31的代码&#xff0c;实现了3254的驱动&#xff0c;同时在mpp的sample中&#xff0c;增加了3254对应的宏&#xff0c;以及相应的初始…

Python监控股价并通过微信提醒

01 Python监控股价并通过微信提醒 炒股盯盘太累&#xff0c;能在设置的买卖点进行智能提醒吗&#xff1f; 没错&#xff0c;python可以帮你实现&#xff1a;通过python编程实现股价实时监控&#xff0c;并在买卖点通过微信发送信息自动提醒&#xff01; 今天&#xff0c;梅朵…

海思烧录工具Hitool使用方法

海思有自己一套独立的烧写工具具Hitool.exe&#xff0c;这是优于国内其他芯片厂家的地方&#xff0c;不会在烧录问题上&#xff0c;耽误您太多时间。 海思的SDK文档放置的很规整&#xff0c;目录清晰&#xff0c;但是对于新手&#xff0c;感觉文档放置路径过深&#xff0c;不好…

海思HI35xx语音识别方案

前言 语音识别是智能化应用的一个重要分支&#xff0c;也是语音交互功能的基础。语音识别基于神经网络算法&#xff0c;借助大数据进行模型训练&#xff0c;据科大讯飞相关数据报道&#xff0c;它们已经能够实现98%以上的准确识别率&#xff0c;同时支持多种外语及国内的一些方…

海思Hi3798MV200机顶盒芯片处理器简介

Hi3798MV200是用于IPTV/OTT机顶盒市场的支持4KP60解码的全4K高性能SOC芯片。集成4核64位高性能Cortex A53处理器和多核高性能2D/3D加速引擎&#xff1b;支持H.265 4Kx2KP60 10bit超高清视频解码&#xff0c;高性能的H.265高清视频编码&#xff0c;HDR视频解码及显示&#xff0c…

TTS语音播报模块UNV6288的使用方法

TTS即text to sound&#xff0c; 输入字符它可以帮你转化为语音输出。 UNV6288可以实现中文、英文、数字的语音合成。用户也可以定义语音大小速度等参数。 这个模块的控制方式很简单&#xff0c;只要通过 TTL 串口向模块发送GBK编码&#xff0c;串口发送什么就播放什么。 另…

基于STM32 + SYN6288语音播报

完整代码下载 https://download.csdn.net/download/zhouml_msn/85592868 一、接线示例&#xff1a; 二、模块重点&#xff1a; 1&#xff1a;5V供电 &#xff0c;功耗约120mA (带图中小喇叭)&#xff1b; 2&#xff1a;最少接3根线&#xff1a;5V, GND, RXD&#xff0c;TXD…

5.32 综合案例2.0 - TTS语音云播报(支持M320开发板)

HaaS506 - TTS语音云播报 简介准备硬件接口代码流程功能实现1、物联网平台开发2、设备端开发代码调试 3.应用平台开发3.1新建‘普通项目’3.2关联产品和设备3.3新建移动应用 简介 用python开发板写的云喇叭&#xff0c;文字转语音&#xff0c;附教程源码 手机端发送文字&#x…

深圳知名语音ic品牌,语音芯片方案公司,多功能语音芯片,WTV890

随着人工智能技术的不断发展&#xff0c;语音交互已成为智能家居、智能医疗、消费类电子等领域的主流趋势。WTV890作为深圳知名的语音IC品牌&#xff0c;凭借着卓越的性能、丰富的扩展功能和灵活的应用&#xff0c;已成为众多需要语音交互的智能设备的首选方案。 WTV890-32N 有…

chatgpt赋能python:用Python生成动画:带你深入了解Python动画生成技术

用Python生成动画&#xff1a;带你深入了解Python动画生成技术 Python作为一门高效的编程语言&#xff0c;已经被广泛应用于各个领域&#xff0c;包括数据分析、机器学习、自动化测试等。除此之外&#xff0c;Python还可以用于生成动画&#xff0c;帮助我们更直观地理解一些复…

银联AID

应用标识 application identifier&#xff1b;AID 由注册的应用提供商标识&#xff08;RID&#xff09;以及专用应用标识符扩展&#xff08;PIX&#xff09;组成 AID:即唯一标识一个应用&#xff0c;分为两部分&#xff0c;RID(5字节)PIX&#xff08;最多11字节&#xff09; …