SEO教程

SEO教程

Products

当前位置:首页 > SEO教程 >

哪个培训机构提供优秀的微网站开发短期培训课程?

96SEO 2026-02-19 12:37 0


哪个培训机构提供优秀的微网站开发短期培训课程?

在前面我们说过父亲和儿子约定打电话的例子#xff0c;不过这是感性的认识序列化反序列化

1.再谈

“约定”。

在前面我们说过父亲和儿子约定打电话的例子不过这是感性的认识今天我们理性的认识一下协议。

socket

结构化的数据就比如说我们在使用QQ群聊时除了消息本身、还能看见头像、时间、昵称。

这些东西都要发给对方。

这些东西都是一个个字符串难道是把消息、头像、时间、昵称都单独发给对方吗那分开发的时候未来群里有成百上千名人大家都发全都分开发接收方还要确定每一部分是谁的进行匹配那这样太恶心了。

实际上这些信息可不是一个个独立个体的而是一个整体。

为了理解暂时当作多个字符串。

把多个字符串形成一个报文或者说打包成一个字符串(方便理解其实是一个字节流)然后在网络中发送。

多变一方便未来在网络里整体发送。

而把多变一的过程我们称之为序列化。

经过序列化的过程变成一个整体后发到网络里经过网络传输发送给对方发是整体当作一个字符串发的。

接收方收的也是整体收的所以收到一个报文或者说字符串。

但是收到的字符串有什么东西我怎么知道qq作为上层要的是谁发的、什么时候、发的什么具体的信息所以接收方收到这个整体字符串后必须把它转成多个字符串这种一变多的过程我们称之为反序列化。

业务结构数据在发送网络中的时候先序列化在发送收到的一定是序列字节流要先进行反序列化然后才能使用。

刚才说过这里用多个字符串不太对只是为了理解实际上未来多个字符串实际是一个结构体。

是以结构体(结构化的数据)作为体现的然后把这个结构体转成一个字符串同理对方收到字符串然后转成对应的结构化的数据。

为什么要把字符串转成结构化数据呢未来这个结构化的数据一定是一个对象然后使用它的时候直接对象.url

、对象.time

未来我们在应用层定协议就是这种结构体类型目的就是把结构化的对象转换成序列化结构发送到网络里然后再把序列化结构转成对应的结构体对象然后上层直接使用对象进行操作

这样光说还是不太理解下面找一个应用场景加深理解刚才的知识。

所以我们写一个网络版计数器。

里面体现出业务协议序列化反序列化在写TCP时要注意TCP时面向字节流的接收方如何保证拿到的是一个完整的报文呢而不是半个、多个这里我们都通过下面写代码的时候解决。

而UDP是面向数据报的接收方收到的一定是一个完整的报文因此不考虑刚才的问题。

2.Cal

_op(op){}public://这里就是我们的约定未来形成

_x;//第一个数字int

_result(result){}public://约定int

_exitcode;

};以前我们写过服务器的代码有些东西就直接用了这里服务器是多进程版本。

如果有新链接来了我们就进行处理因此给一个handlerEntry函数这里没写在类里主要是为了解耦。

并且也把业务逻辑进行解耦给一个回调函数handlerEntry函数你做你的序列化反序列化等一系列工作和我没关系。

我只做我的工作就行了。

//业务逻辑处理

resp...;//callback(req,resp);//

4.对响应Response进行序列化//

error);continue;}logMessage(NORMAL,

accpet

这里就是一个sock,未来通信我们就用这个sock,tcp面向字节流的,后序全部都是文件操作!//

version2

0){close(_listensock);handlerEntry(sock,

func);close(sock);exit(0);}close(sock);}}//。

private:uint16_t

_port;int

根据req进行业务处理填充resp不用管理任何读取和写入序列化和反序列化等任何细节

void

2){Usage(argv[0]);exit(USAGG_ERR);}uint16_t

serverport

atoi(argv[1]);unique_ptrCalServer

tsv(new

CalServer(serverport));tsv-initServer();tsv-start(Cal);return

}整体就是这样的逻辑我们现在把软件分成三层。

第一层获取链接进行处理第二层handlerEntery进行序列化反序列化等一系列工作第三层进行业务处理callback。

【一个】完整的请求因为TCP是面向字节流的我们保证不了所以要明确

TCP有自己内核级别的发送缓冲区和接收缓冲区而应用层也有自己的缓冲区我们自己写的代码调用readwrite发送读取使用的buffer就是对应缓冲区。

其实我们调用的所有的发送函数根本就不是把数据发送到网络中

write只是把数据从应用层缓冲区拷贝到TCP发送缓冲区由TCP协议决定什么时候把数据发送到网络发多少出错了怎么办。

所以TCP协议叫做传输控制协议

最终数据经过网络发送被服务端放到自己的接收缓冲区里然后我们在应用层调用read实际在等接收缓冲区里有没有数据有数据就把数据拷贝应用层的缓冲区。

没有数据就是说接收缓冲区是空的read就会被阻塞。

C-S:

tcp发送的本质其实就是将数据从c的发送缓冲区拷贝到s的接收缓冲区。

S-C:

tcp发送的本质其实就是将数据从s的发送缓冲区拷贝到c的接收缓冲区。

c-s发并不影响s-c发因为用的是不同的成对的缓冲区所以tcp是全双工的

这里主要想说的是tcp在进行发送数据的时候发收方一直发数据但是对方正在做其他事情来不及读数据所以导致接收方的接收缓冲区里面存在很多的报文因为是TCP面向字节流的所以这些报文是挨在一起最终读的时候怎么保证读到的是一个完整的报文交给上层处理而不是半个多个。

就是因为我们有接收缓冲区的存在因此首先我们要解决读取的问题。

定长特殊符号自描述方式

我们给每个报文前面带一个有效载荷长度的字段未来我先读到这个长度根据这个长度在读取若干字节这样就能读取到一个报文一个能读到n个也能读到。

有效载荷里面是请求或者响应序列化的结果。

//有效载荷-报文

还有不管是请求和响应未来都需要做序列化和反序列化因此在这两个类中都要包含这两个函数。

class

};关于这个序列化我们可以自己写也可以用现成的不过我们是初学先自己写感受一下等都写完我们在介绍现成的。

#define

req_str;//代表报文分离之后读取到的字符串(有效载荷)//

对请求Request反序列化//

(!req.deserialize(req_str))return;//

计算机处理req.x,

根据req进行业务处理填充resp不用管理任何读取和写入序列化和反序列化等任何细节

void

{//req已经有结构化完成的数据啦你可以直接使用resp._exitcode

OK;resp._result

DIV_ERR;elseresp._resultreq._x/req._y;}break;case

%:{if

MOD_ERR;elseresp._resultreq._x%req._y;}break;default:resp._exitcode

OPER_ERR;break;}}现在对响应进行序列化反序列化

class

req_str;//代表报文分离之后读取到的字符串(有效载荷)//

对请求Request反序列化//

(!req.deserialize(req_str))return;//

计算机处理req.x,

(!resp.serialize(resp_str))return;//

然后我们在发送响应//

首先得是一个报文因此我们把序列化形成的字符串加上特定的格式形成一个报文

content_len\r\nx

to_string(text.size());send_string

LINE_SEP;send_string

req_str;//代表报文分离之后读取到的字符串(有效载荷)//

对请求Request反序列化//

(!req.deserialize(req_str))return;//

计算机处理req.x,

(!resp.serialize(resp_str))return;//

然后我们在发送响应//

}新的接口函数send和write一模一样不过多了一个参数flags发送方式默认为0后面解释。

content_len\r\nx

y\r\n我们在写一个recvpackge读取函数让它进行处理。

只要这个函数返回了走到下面一定是读取到了一个完整的报文。

然后对这个报文进行处理只要有效载荷。

void

inbuffer;//每次从缓冲区拿到的数据放到inbuffer里while

(true){string

【一个】完整的请求//把从sock读取的数据最后放到inbuffer里从inbuffer里面拿到一个完整的请求放到req_textif

(!recvpackge(sock,

我们保证我们req_text里面一定是一个完整的请求content_len\r\nx

y\r\nif

buffer;//可能一次没用读到完整的报文,这里使用的是auto

pos

没读到一个完整报文continue;//inbuffer.size()

content_len/r/nx

//如果inbuffer.size()大于或等于一个完整报文的长度说明inbuffer里面至少有一个完整报文string

text_len_string

total_len)//也没有读到一个完整报文continue;//

inbuffer.substr(0,

total_len);//拿到一个完整报文inbuffer.erase(0,

total_len);//把拿走的报文从inbuffer缓冲区里减去break;}else{return

false;}}return

这里我们增加一些打印信息最后运行可以看的到序列化反序列的过程。

#pragma

to_string(text.size());send_string

LINE_SEP;send_string

buffer;//可能一次没用读到完整的报文,这里使用的是auto

pos

没读到一个完整报文continue;//inbuffer.size()

content_len/r/nx

//如果inbuffer.size()大于或等于一个完整报文的长度说明inbuffer里面至少有一个完整报文string

text_len_string

total_len);//拿到一个完整报文inbuffer.erase(0,

total_len);//把拿走的报文从inbuffer缓冲区里减去cout

处理后#inbuffer:\n

1,SOCKET_ERR,BIND_ERR,LISTEN_ERR

};const

我们保证我们req_text里面一定是一个完整的请求content_len\r\nx

y\r\nif

(!req.deserialize(req_str))return;//

计算机处理req.x,

(!resp.serialize(resp_str))return;cout

计算完成,

error);exit(SOCKET_ERR);}logMessage(NORMAL,

socker

sizeof(local));local.sin_family

htons(_port);local.sin_addr.s_addr

INADDR_ANY;

error);exit(BIND_ERR);}logMessage(NORMAL,

bind

error);exit(LISTEN_ERR);}logMessage(NORMAL,

listen

error);continue;}logMessage(NORMAL,

accpet

这里就是一个sock,未来通信我们就用这个sock,tcp面向字节流的,后序全部都是文件操作!//

version2

0){close(_listensock);handlerEntery(sock,

func);close(sock);exit(0);}close(sock);}}~CalServer(){}private://

string

根据req进行业务处理填充resp不用管理任何读取和写入序列化和反序列化等任何细节

void

req已经有结构化完成的数据啦你可以直接使用resp._exitcode

OK;resp._result

DIV_ERR;elseresp._resultreq._x/req._y;}break;case

%:{if

MOD_ERR;elseresp._resultreq._x%req._y;}break;default:resp._exitcode

OPER_ERR;break;}}//

2){Usage(argv[0]);exit(USAGG_ERR);}uint16_t

serverport

atoi(argv[1]);unique_ptrCalServer

tsv(new

CalServer(serverport));tsv-initServer();tsv-start(Cal);return

}2.Cal

sizeof(server));server.sin_family

htons(_serverport);server.sin_addr.s_addr

inet_addr(_serverip.c_str());if

(connect(_sockfd,

reqParseLine(msg);//构建Request对象string

req_str;req.serialize(req_str);//序列化string

send_stringEnlenth(req_str);//加报头send(_sockfd,send_string.c_str(),send_string.size(),0);//

读//

recvpackge里我们是按照特殊格式进行读取的因此这里直接用//

result\r\nstring

resp_text,resp_str;if(!recvpackge(_sockfd,inbuffer,resp_text))continue;if(!Delenth(resp_text,resp_str))continue;//

exitcode

resp;resp.deserialize(resp_str);coutexitcode:

resp._resultendl;}}}//这里有各种方法可以选自己喜欢的处理方式Request

ParseLine(const

i0;imsg.size();i){if(isdigit(msg[i])

req;req._xstoi(left);req._ystoi(right);req._opmsg[pos];return

_serverip;uint16_t

};现在服务端和客户端都写好了运行一下这里我们打印出一些信息能看到序列化和反序列化的过程。

TCP是面向字节流的需要考虑保证读到的是一个完整报文、获取有效载荷、序列化、反序列化。

4.Json

上面是我们手写序列化和反序列化和协议帮助我们理解这里序列化和反序列化自己写的有的挫。

对于序列化和反序列化有现成的解决方案绝对不会自己去写。

但是没说协议不能自己定

Jsonprotobufxml

里面属性是以K和V的形式呈现出来的键值对未来我们可以以KV形式设置提取可以以KV形式提取。

安装Json库

//安装c的json库下面在代码里我们使用了条件编译方便自己用Json和自己序列化反序列方案切换。

编译的时候想用Json方案-DMYSELF不想用#-DMYSELF

注释掉

calservercalclient:CalClient.ccg

-stdc11

root;//Json::Value是一个万能对象用来接收任意类型//Json是KV的格式因此我们要给它设置KV方便后面提取它//x虽然是个整型但是实际在保存到Json里它会把所有内容转成字符串root[first]

_x;root[second]

_op;//Json形成字符串有两种风格我们选其中一种Json::FastWriter

write;//

write.write(root);//里面自动组序列化返回值是一个string

#endifreturn

root);//从in这个流中做反序列化放到root里//根据K提取V//不过Json默认把所有数据当成字符串_x

root[first].asInt();//把字符串转成对于的类型_y

root[oper].asInt();//char本来就是按ASCII码存的这里也把当它当成整数#endifreturn

true;}public:int

自定义协议说人话就是定义一个结构化的对象有了这个结构化的对象未来客户端和服务端可以进行来回的发送。

约定体现在这个结构化对象里面的成员变量都代表了什么意思。

为什么一定是这样的格式而不能是其他格式。

如op为什么一定是±*/不能是其他这些都是约定好的。

拿到结果先看哪一个后看哪一个。

exitcode为0是什么意思不为0是什么意思。

都是规定好的。

这就是协议。

我们今天就只写了一种协议RequestResponse未来如果想用Request1Response1等等定义100对协议都是可以的。

每一对协议做不同的工作。

y\r\n未来解析协议的时候可以把协议编号拿到然后根据编号区分清楚用的是那个RequestResponse对象。

目前基本socket写完一般服务器设计原则和方式(多进程、多线程、线程池)常见的各种场景自定义协议序列化和反序列化都已经学了。

所以未来我们就可以用这三大构成自己自由去写服务器了。

有没有人已经针对常见场景早就已经写好了常见的协议软件供我们使用呢

当然了最典型的HTTP/HTTPS。

未来它们做的事情和我们以前做的事情是一样的只不过HTTP是结合它的应用场景来谈的。

下篇博客我们具体详谈



SEO优化服务概述

作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。

百度官方合作伙伴 白帽SEO技术 数据驱动优化 效果长期稳定

SEO优化核心服务

网站技术SEO

  • 网站结构优化 - 提升网站爬虫可访问性
  • 页面速度优化 - 缩短加载时间,提高用户体验
  • 移动端适配 - 确保移动设备友好性
  • HTTPS安全协议 - 提升网站安全性与信任度
  • 结构化数据标记 - 增强搜索结果显示效果

内容优化服务

  • 关键词研究与布局 - 精准定位目标关键词
  • 高质量内容创作 - 原创、专业、有价值的内容
  • Meta标签优化 - 提升点击率和相关性
  • 内容更新策略 - 保持网站内容新鲜度
  • 多媒体内容优化 - 图片、视频SEO优化

外链建设策略

  • 高质量外链获取 - 权威网站链接建设
  • 品牌提及监控 - 追踪品牌在线曝光
  • 行业目录提交 - 提升网站基础权威
  • 社交媒体整合 - 增强内容传播力
  • 链接质量分析 - 避免低质量链接风险

SEO服务方案对比

服务项目 基础套餐 标准套餐 高级定制
关键词优化数量 10-20个核心词 30-50个核心词+长尾词 80-150个全方位覆盖
内容优化 基础页面优化 全站内容优化+每月5篇原创 个性化内容策略+每月15篇原创
技术SEO 基本技术检查 全面技术优化+移动适配 深度技术重构+性能优化
外链建设 每月5-10条 每月20-30条高质量外链 每月50+条多渠道外链
数据报告 月度基础报告 双周详细报告+分析 每周深度报告+策略调整
效果保障 3-6个月见效 2-4个月见效 1-3个月快速见效

SEO优化实施流程

我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:

1

网站诊断分析

全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。

2

关键词策略制定

基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。

3

技术优化实施

解决网站技术问题,优化网站结构,提升页面速度和移动端体验。

4

内容优化建设

创作高质量原创内容,优化现有页面,建立内容更新机制。

5

外链建设推广

获取高质量外部链接,建立品牌在线影响力,提升网站权威度。

6

数据监控调整

持续监控排名、流量和转化数据,根据效果调整优化策略。

SEO优化常见问题

SEO优化一般需要多长时间才能看到效果?
SEO是一个渐进的过程,通常需要3-6个月才能看到明显效果。具体时间取决于网站现状、竞争程度和优化强度。我们的标准套餐一般在2-4个月内开始显现效果,高级定制方案可能在1-3个月内就能看到初步成果。
你们使用白帽SEO技术还是黑帽技术?
我们始终坚持使用白帽SEO技术,遵循搜索引擎的官方指南。我们的优化策略注重长期效果和可持续性,绝不使用任何可能导致网站被惩罚的违规手段。作为百度官方合作伙伴,我们承诺提供安全、合规的SEO服务。
SEO优化后效果能持续多久?
通过我们的白帽SEO策略获得的排名和流量具有长期稳定性。一旦网站达到理想排名,只需适当的维护和更新,效果可以持续数年。我们提供优化后维护服务,确保您的网站长期保持竞争优势。
你们提供SEO优化效果保障吗?
我们提供基于数据的SEO效果承诺。根据服务套餐不同,我们承诺在约定时间内将核心关键词优化到指定排名位置,或实现约定的自然流量增长目标。所有承诺都会在服务合同中明确约定,并提供详细的KPI衡量标准。

SEO优化效果数据

基于我们服务的客户数据统计,平均优化效果如下:

+85%
自然搜索流量提升
+120%
关键词排名数量
+60%
网站转化率提升
3-6月
平均见效周期

行业案例 - 制造业

  • 优化前:日均自然流量120,核心词无排名
  • 优化6个月后:日均自然流量950,15个核心词首页排名
  • 效果提升:流量增长692%,询盘量增加320%

行业案例 - 电商

  • 优化前:月均自然订单50单,转化率1.2%
  • 优化4个月后:月均自然订单210单,转化率2.8%
  • 效果提升:订单增长320%,转化率提升133%

行业案例 - 教育

  • 优化前:月均咨询量35个,主要依赖付费广告
  • 优化5个月后:月均咨询量180个,自然流量占比65%
  • 效果提升:咨询量增长414%,营销成本降低57%

为什么选择我们的SEO服务

专业团队

  • 10年以上SEO经验专家带队
  • 百度、Google认证工程师
  • 内容创作、技术开发、数据分析多领域团队
  • 持续培训保持技术领先

数据驱动

  • 自主研发SEO分析工具
  • 实时排名监控系统
  • 竞争对手深度分析
  • 效果可视化报告

透明合作

  • 清晰的服务内容和价格
  • 定期进展汇报和沟通
  • 效果数据实时可查
  • 灵活的合同条款

我们的SEO服务理念

我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。

提交需求或反馈

Demand feedback