微调神经机器翻译模型全流程

MBART: Multilingual Denoising Pre-training for Neural Machine Translation

模型下载

mBART 是一个基于序列到序列的去噪自编码器,使用 BART 目标在多种语言的大规模单语语料库上进行预训练。mBART 是首批通过去噪完整文本在多种语言上预训练序列到序列模型的方法之一,而以往的方法则仅集中在编码器、解码器或重构文本的部分内容。

首先需要在github上下载mbart的预训练模型,我们要完成的任务是微调:README
在这里插入图片描述
下载mbart.CC25模型,下载解压后的目录如下:

├── mbart.cc25.v2└── dict.txt└── model.pt└── sentence.bpe.model

dict是模型的词典文件,model是mbart的预训练模型,sentence.bpe.model是sentencepiece训练分词的模型。
我们在en->vi双语对上对预训练模型进行微调:
在这里插入图片描述
数据为IWSLT15的双语对,下载好数据之后对训练集、验证集和测试集重新命名,整理后的目录如下

├── en_vi └── test.en_XX└── test.vi_VN└── train.en_XX└── train.vi_VN└── valid.en_XX└── valid.vi_VN

环境准备

这里需要特定的fairseq版本来完成以下的这些命令,因此推荐新创建一个conda环境来隔离版本,这里我们命名为mbart_ft.

fairseq=0.10.2
python=3.8
numpy=1.19.5

数据分词

首先使用sentencepiece模型对数据进行分词,由于原文中描述没有额外的 true-casing、normalizing punctuation / characters.因此我们直接分词即可。

#!/bin/bashSPM=/path/to/sentencepiece/build/src/spm_encode
MODEL=/mbart/mbart.cc25.v2/sentence.bpe.model
DATA=/mbart/en_vi 
DEST=/mbart/en_vi/spm
TRAIN=train         
VALID=valid        
TEST=test           
SRC=en_XX              
TGT=vi_VN              ${SPM} --model=${MODEL} < ${DATA}/${TRAIN}.${SRC} > ${DEST}/${TRAIN}.spm.${SRC} &
${SPM} --model=${MODEL} < ${DATA}/${TRAIN}.${TGT} > ${DEST}/${TRAIN}.spm.${TGT} &
${SPM} --model=${MODEL} < ${DATA}/${VALID}.${SRC} > ${DEST}/${VALID}.spm.${SRC} &
${SPM} --model=${MODEL} < ${DATA}/${VALID}.${TGT} > ${DEST}/${VALID}.spm.${TGT} &
${SPM} --model=${MODEL} < ${DATA}/${TEST}.${SRC} > ${DEST}/${TEST}.spm.${SRC} &
${SPM} --model=${MODEL} < ${DATA}/${TEST}.${TGT} > ${DEST}/${TEST}.spm.${TGT} &wait
echo "SentencePiece encoding completed!"

我们创建spm目录,分词后的目录文件为:

├── en_vi├── spm └── test.spm.en_XX└── test.spm.vi_VN└── train.spm.en_XX└── train.spm.vi_VN└── valid.spm.en_XX└── valid.spm.vi_VN

数据预处理

使用fairseq将数据处理为满足训练的、输入模型的格式。包含两种语言的词典文件、二进制格式和分词转换为id的文件。

#!/bin/bashBASEDIR=/mbart/en_vi
DATA=${BASEDIR}/spm
DEST=${BASEDIR}/ids
DICT=/mbart/mbart.cc25.v2/dict.txt
SRC=en_XX
TGT=en_viTRAIN=train
VALID=valid
TEST=testfairseq-preprocess \
--source-lang ${SRC} \
--target-lang ${TGT} \
--trainpref ${DATA}/${TRAIN}.spm \
--validpref ${DATA}/${VALID}.spm \
--testpref ${DATA}/${TEST}.spm  \
--destdir ${DEST}/  \
--thresholdtgt 0 \
--thresholdsrc 0 \
--srcdict ${DICT} \
--tgtdict ${DICT} \
--workers 70

预处理后的模型数据准备的目录为:

├── en_vi├── ids └── dict.en_XX.txt└── dict.vi_VN.txt└── preprocess.log└── test.en_XX-vi_VN.en_XX.bin└── test.en_XX-vi_VN.en_XX.idx└── test.en_XX-vi_VN.vi_VN.bin└── test.en_XX-vi_VN.vi_VN.idx└── train.en_XX-vi_VN.en_XX.bin└── train.en_XX-vi_VN.en_XX.idx└── train.en_XX-vi_VN.vi_VN.bin└── train.en_XX-vi_VN.vi_VN.idx└── valid.en_XX-vi_VN.en_XX.bin└── valid.en_XX-vi_VN.en_XX.idx└── valid.en_XX-vi_VN.vi_VN.bin└── valid.en_XX-vi_VN.vi_VN.idx

训练集和验证集在训练过程中被用到,而测试集只在评价生成中被用到。

模型的训练

需要注意的是,与官方文档设置的参数相比,有一处需要修改。
--max-update 40000:模型参数更新次数。
----total-num-update 40000 这是设置学习率调度器的更新次数,即学习率更新40k次训练停止。
在mbart的原文中:

We use a maximum of 40K training updates for all low and medium resource pairs and 100K for high resource pairs.

我们的en-vi双语数据属于低资源语言对,因此参数更新次数40K次,即应该设置--max-update 40000

#!/bin/bash
source /path/to/conda/etc/profile.d/conda.sh
conda activate mbart_ftBASEDIR=/mbart/en_vi
PRETRAIN=/mbart/mbart.cc25.v2/model.pt # 已下载的预训练模型路径
DATA=${BASEDIR}/ids    # 预处理后的二进制数据路径SRC=en_XX
TGT=vi_VNlangs=ar_AR,cs_CZ,de_DE,en_XX,es_XX,et_EE,fi_FI,fr_XX,gu_IN,hi_IN,it_IT,ja_XX,kk_KZ,ko_KR,lt_LT,lv_LV,my_MM,ne_NP,nl_XX,ro_RO,ru_RU,si_LK,tr_TR,vi_VN,zh_CNfairseq-train ${DATA} \--encoder-normalize-before --decoder-normalize-before \--arch mbart_large --layernorm-embedding \--task translation_from_pretrained_bart \--source-lang ${SRC} --target-lang ${TGT} \--criterion label_smoothed_cross_entropy --label-smoothing 0.2 \--optimizer adam --adam-eps 1e-06 --adam-betas '(0.9, 0.98)' \--lr-scheduler polynomial_decay --lr 3e-05 --warmup-updates 2500 --max-update 40000 \--dropout 0.3 --attention-dropout 0.1 --weight-decay 0.0 \--max-tokens 1024 --update-freq 2 \--save-interval 1 --save-interval-updates 5000 --keep-interval-updates 10 --no-epoch-checkpoints \--seed 222 --log-format simple --log-interval 2 \--restore-file $PRETRAIN \--reset-optimizer --reset-meters --reset-dataloader --reset-lr-scheduler \--langs $langs \--save-dir ${BASEDIR} \--ddp-backend no_c10d

在一块RTX 4090显卡上,运行3个小时后,训练结束。我们设置了每5000次更新保存一次检查点,微调模型保存的文件位置为 --save-dir ${BASEDIR}
微调后的目录文件为:

├── en_vi├── ids ├── spm└── dict.en_XX.txt└── checkpoint_2_5000.pt└── checkpoint_4_10000.pt└── checkpoint_6_15000.pt└── checkpoint_8_20000.pt└── checkpoint_10_25000.pt└── checkpoint_12_30000.pt└── checkpoint_14_35000.pt└── checkpoint_16_40000.pt└── checkpoint_best.pt└── checkpoint_last.pt└── ...train...test...valid

模型的解码

我们使用checkpoint_best.pt对其进行解码以及测BLEU分数。
这里我将分词模型复制到了en_vi文件夹中,并且添加--cpu使得解码在cpu上运行。解码生成的文件为/mbart/en_vi/ids/en_vi


2025.1.13修订:
需要注意的是,相比于官方文档,这里删除了--bpe "sentencepiece"--sentencepiece-model $model_dir/sentence.bpe.model以及--sacrebleu
若保留--sacrebleu,由于版本间不匹配会报错
若保留--bpe "sentencepiece",则除了模型推理行“H”,其他源句子、目标句子和行“D”均没有空格出现。说明解码过程中并不需要此参数。
--remove-bpe 'sentencepiece':用于去除分词过程中产生的spm标记。

#!/bin/bash
source /path/to/conda/etc/profile.d/conda.sh
conda activate mbart_ft
model_dir=/mbart/en_vi/ids langs=ar_AR,cs_CZ,de_DE,en_XX,es_XX,et_EE,fi_FI,fr_XX,gu_IN,hi_IN,it_IT,ja_XX,kk_KZ,ko_KR,lt_LT,lv_LV,my_MM,ne_NP,nl_XX,ro_RO,ru_RU,si_LK,tr_TR,vi_VN,zh_CN
TOKENIZER=${model_dir}/sentence.bpe.modelfairseq-generate ${model_dir} \--path $model_dir/../checkpoint_best.pt \--task translation_from_pretrained_bart \--gen-subset test \--cpu \-t vi_VN -s en_XX \--remove-bpe 'sentencepiece' \--batch-size 32 \--langs $langs > ${model_dir}/en_vi

查看生成文件en_vi的片段:

S-74	I lost all hope .[en_XX]
T-74	Tôi hoàn toàn tuyệt vọng .
H-74	-0.4808153808116913	Tôi đã mất hết hy vọng .
D-74	-0.4808153808116913	Tôi đã mất hết hy vọng .
P-74	-0.3194 -0.9490 -0.5736 -0.8777 -0.7397 -0.0389 -0.4746 -0.2814 -0.2920 -0.2618
S-372	Today I am 22 .[en_XX]
T-372	Hôm nay tôi 22 tuổi .
H-372	-0.3478223383426666	Hôm nay tôi 22 tuổi .
D-372	-0.3478223383426666	Hôm nay tôi 22 tuổi .
P-372	-0.5605 -0.0631 -0.4549 -0.2989 -0.4617 -0.4079 -0.3166 -0.3061 -0.2606
S-336	Thank you very much .[en_XX]
T-336	Cám ơn rất nhiều .
H-336	-0.46486935019493103	Cám ơn các bạn rất nhiều .
D-336	-0.46486935019493103	Cám ơn các bạn rất nhiều .
P-336	-1.8484 -0.0979 -0.1278 -0.9053 -0.2160 -0.4894 -0.1446 -0.4404 -0.2856 -0.3061 -0.2521
S-1267	Thank you very much .[en_XX]
T-1267	Cảm ơn rất nhiều .
H-1267	-0.46486935019493103	Cám ơn các bạn rất nhiều .
D-1267	-0.46486935019493103	Cám ơn các bạn rất nhiều .
P-1267	-1.8484 -0.0979 -0.1278 -0.9053 -0.2160 -0.4894 -0.1446 -0.4404 -0.2856 -0.3061 -0.2521
S-21	But many die .[en_XX]
T-21	Nhưng rất nhiều người đã chết .
H-21	-0.5680863261222839	Nhưng nhiều người chết .
D-21	-0.5680863261222839	Nhưng nhiều người chết .
P-21	-0.3266 -1.4395 -0.1804 -1.2362 -0.5122 -0.2999 -0.2973 -0.2526

S:是源句子,在en->vi双语对上,源语言是英语。
T:是人工翻译句子,即测试集中的句子;
H:是模型输出的解码句子,第一个数字为其得分;
D:第一个数字为得分和H一致,但相比于H去掉了所有的空格,和S、T格式相同;
P:翻译过程中每个单词的预测概率。
运行解码脚本后,在ids目录中会生成 en_vi 文件。

├── en_vi├── ids └── sentence.bpe.model└── en_vi└── train...test...valid...dict...├── spm├── train...valid...test...

模型的评价

cat en_vi | grep -P "^H" |sort -V |cut -f 3- | sed 's/\[vi_VN\]//g' > en_vi.hyp
cat en_vi | grep -P "^T" |sort -V |cut -f 2- | sed 's/\[vi_VN\]//g' > en_vi.ref
sacrebleu  en_vi.ref -i en_vi.hyp -m bleu

这里将 H 开头的行提取,并去掉前两个字段,仅保留模型输出的解码句子,将他们合成 en_vi.hyp文件;
将 T 开头的行提取,并去掉第一个字段,保留test文件中的目标句子,将他们合成 en_vi.ref 文件。
这两行代码运行后,目录ids中应该多出两个文件。

├── en_vi├── ids └── en_vi└── en_vi.hyp└── en_vi.ref└── train...test...valid...dict...├── spm├── train...valid...test...

这两个文件的行数应该一致,使用sacrebleu来测bleu的分数,指定 -tok 分词方式是 “spm” 即sentencepiece。
我们测试的模型评价结果为:

{"name": "BLEU","score": 34.7,"signature": "nrefs:1|case:mixed|eff:no|tok:13a|smooth:exp|version:2.4.3","verbose_score": "66.2/42.0/27.8/18.7 (BP = 1.000 ratio = 1.007 hyp_len = 33986 ref_len = 33738)","nrefs": "1","case": "mixed","eff": "no","tok": "13a","smooth": "exp","version": "2.4.3"
}

附录

2025.1.13修订:
原版本未删除--bpe "sentencepiece"--sentencepiece-model $model_dir/sentence.bpe.model参数,fairseq推理后生成的en_vi文件为:

S-74    Ilostallhope.[en_XX]
T-74    Tôihoàntoàntuyệtvọng.
H-74    -0.4808153808116913     Tôi đã mất hết hy vọng .
D-74    -0.4808153808116913     Tôiđãmấthếthyvọng.
P-74    -0.3194 -0.9490 -0.5736 -0.8777 -0.7397 -0.0389 -0.4746 -0.2814 -0.2920 -0.2618
S-372   TodayIam22.[en_XX]
T-372   Hômnaytôi22tuổi.
H-372   -0.3478223383426666     Hôm nay tôi 22 tuổi .
D-372   -0.3478223383426666     Hômnaytôi22tuổi.
P-372   -0.5605 -0.0631 -0.4549 -0.2989 -0.4617 -0.4079 -0.3166 -0.3061 -0.2606
S-336   Thankyouverymuch.[en_XX]
T-336   Cámơnrấtnhiều.
H-336   -0.46486935019493103    Cám ơn các bạn rất nhiều .
D-336   -0.46486935019493103    Cámơncácbạnrấtnhiều.
P-336   -1.8484 -0.0979 -0.1278 -0.9053 -0.2160 -0.4894 -0.1446 -0.4404 -0.2856 -0.3061 -0.2521
S-1267  Thankyouverymuch.[en_XX]
T-1267  Cảmơnrấtnhiều.
H-1267  -0.46486935019493103    Cám ơn các bạn rất nhiều .
D-1267  -0.46486935019493103    Cámơncácbạnrấtnhiều.
P-1267  -1.8484 -0.0979 -0.1278 -0.9053 -0.2160 -0.4894 -0.1446 -0.4404 -0.2856 -0.3061 -0.2521
S-21    Butmanydie.[en_XX]
T-21    Nhưngrấtnhiềungườiđãchết.
H-21    -0.5680863261222839     Nhưng nhiều người chết .
D-21    -0.5680863261222839     Nhưngnhiềungườichết.
P-21    -0.3266 -1.4395 -0.1804 -1.2362 -0.5122 -0.2999 -0.2973 -0.2526

可以看到,测试集源句子S以及目标句子T的空格被误删除。由此提取的模型生成文件en_vi.hyp和翻译参考文件en_vi.ref同样误删空格。且模型输出句子H是正常的,这就说明是在解码过程中出现的问题。


2025.1.15修订:
在使用sacrebleu测bleu分数时,-tok 参数指定分词器。
默认为“13a”,即不添加此参数时的默认,我们测出评分为34.7.
指定为"spm" 等同于 “flores101”,使用基于Flores-101和Flores-200数据集构建的SentencePiece模型。

{"name": "BLEU","score": 35.4,"signature": "nrefs:1|case:mixed|eff:no|tok:flores101|smooth:exp|version:2.4.3","verbose_score": "66.3/42.8/28.8/19.5 (BP = 0.997 ratio = 0.997 hyp_len = 34971 ref_len = 35063)","nrefs": "1","case": "mixed","eff": "no","tok": "flores101","smooth": "exp","version": "2.4.3"
}

指定为“none”,将不应用任何分词,测出评分为:

{"name": "BLEU","score": 34.6,"signature": "nrefs:1|case:mixed|eff:no|tok:none|smooth:exp|version:2.4.3","verbose_score": "66.2/42.0/27.8/18.6 (BP = 1.000 ratio = 1.008 hyp_len = 33948 ref_len = 33682)","nrefs": "1","case": "mixed","eff": "no","tok": "none","smooth": "exp","version": "2.4.3"
}

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

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

相关文章

浔川社团官方文章被 Devpress 社区收录!

浔川社团官方文章被 Devpress 社区收录&#xff01; 亲爱的浔川社团成员们以及关注我们的朋友们&#xff1a; 在这个充满活力与机遇的社团发展历程中&#xff0c;我们迎来了一则令人振奋的喜讯&#xff01;浔川社团精心创作的官方文章&#xff0c;成功被 Devpress 社区收录啦&a…

STM32网络通讯之CubeMX实现LWIP项目设计(十五)

STM32F407 系列文章 - ETH-LWIP-CubeMX&#xff08;十五&#xff09; 目录 前言 一、软件设计 二、CubeMX实现 1.配置前准备 2.CubeMX配置 1.ETH模块配置 2.时钟模块配置 3.中断模块配置 4.RCC及SYS配置 5.LWIP模块配置 3.生成代码 1.main文件 2.用户层源文件 3.…

简单组合逻辑

多路选择器 在多路数据传输过程中&#xff0c;能够将任意一路选出来的电路叫做数据选择器&#xff0c;也称多路选择器。对于一个具有2^n个输入和一个输出的多路选择器&#xff0c;有n个选择变量&#xff0c;多路选择器也是FPGA内部的一个基本资源&#xff0c;主要用于内部信号的…

【Unity-Game4Automation PRO 插件】

Game4Automation PRO 插件 是一个用于 Unity 引擎 的工业自动化仿真工具&#xff0c;它提供了对工业自动化领域的仿真和虚拟调试支持&#xff0c;特别是在与工业机器人、生产线、PLC 系统的集成方面。该插件旨在将工业自动化的实时仿真与游戏开发的高质量 3D 可视化能力结合起来…

【安卓开发】【Android】总结:安卓技能树

【持续更新】 对笔者在安卓开发的实践中认为必要的知识点和遇到的问题进行总结。 一、基础知识部分 1、Android Studio软件使用 软件界面 最新的版本是瓢虫&#xff08;Ladybug&#xff09;&#xff0c;bug的确挺多。笔者更习惯使用电鳗&#xff08;Electric Eel&#xff0…

鸿蒙打包发布

HarmonyOS应用/元服务发布&#xff08;打包发布&#xff09; https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V13/ide-publish-app-V13?catalogVersionV13 密钥&#xff1a;包含非对称加密中使用的公钥和私钥&#xff0c;存储在密钥库文件中&#xff0c;格式…

Spring Boot 下的Swagger 3.0 与 Swagger 2.0 的详细对比

先说结论&#xff1a; Swgger 3.0 与Swagger 2.0 区别很大&#xff0c;Swagger3.0用了最新的注释实现更强大的功能&#xff0c;同时使得代码更优雅。 就个人而言&#xff0c;如果新项目推荐使用Swgger 3.0&#xff0c;对于工具而言新的一定比旧的好&#xff1b;对接于旧项目原…

神经网络基础-价格分类案例

文章目录 1. 需求分析2. 导入所需工具包3. 构建数据集4. 构建分类网络模型5. 训练模型6. 模型训练7. 评估模型8. 模型优化 学习目标&#xff1a; 掌握构建分类模型流程动手实践整个过程 1. 需求分析 小明创办了一家手机公司&#xff0c;他不知道如何估算手机产品的价格。为了…

SAP 固定资产常用的数据表有哪些,他们是怎么记录数据的?

在SAP系统中&#xff0c;固定资产管理&#xff08;FI-AA&#xff09;涉及多个核心数据表&#xff0c;用于记录资产主数据、折旧、交易等。以下是常用的数据表及其记录数据的逻辑&#xff1a; 1. ANKT - 资产主数据表 功能&#xff1a;存储资产主数据的文本描述。 字段&#x…

光伏储能电解水制氢仿真模型Matlab/Simulink

今天更新的内容为光伏储能制氢技术&#xff0c;这个方向我之前在21年就系统研究并发表过相关文章&#xff0c;经过这几年的发展&#xff0c;绿色制氢技术也受到更多高校的注意&#xff0c;本篇博客也是在原先文章的基础上进行更新。 首先让大家熟悉一下绿氢制取技术这个概念&a…

Redis 3.2.1在Win10系统上的安装教程

诸神缄默不语-个人CSDN博文目录 这个文件可以跟我要&#xff0c;也可以从官网下载&#xff1a;https://github.com/MicrosoftArchive/redis/releases 这个是微软以前维护的Windows版Redis安装包&#xff0c;如果想要比较新的版本可以从别人维护的项目里下&#xff08;https://…

基于springboot+vue.js+uniapp技术开发的一套大型企业MES生产管理系统源码,支持多端管理

企业级智能制造MES系统源码&#xff0c;技术架构&#xff1a;springboot vue-element-plus-admin 企业级云MES全套源码&#xff0c;支持app、小程序、H5、台后管理端 MES指的是制造企业生产过程执行系统&#xff0c;是一套面向制造企业车间执行层的生产信息化管理系统。MES系…

【Redis】Redis事务和Lua脚本的区别

Redis事务 概念 事务&#xff1a;Redis事务是一组命令的集合&#xff0c;这些命令会被序列化地执行&#xff0c;中间不会被其他命令插入。 MULTI/EXEC&#xff1a;Redis事务通过MULTI命令开始&#xff0c;通过EXEC命令执行所有已入队的命令。 特点 原子性&#xff1a; 事务…

frameworks 之 AMS与ActivityThread交互

frameworks 之 AMS与ActivityThread交互 1. 类关系2. 流程2.1 AMS流程2.1 ActivityThread流程 3. 堆栈 讲解AMS 如何和 ActivityThread 生命周期调用流程 涉及到的类如下 frameworks/base/core/java/android/app/servertransaction/ResumeActivityItem.javaframeworks/base/cor…

Jmeter 简单使用、生成测试报告(一)

一、下载Jmter 去官网下载&#xff0c;我下载的是apache-jmeter-5.6.3.zip&#xff0c;解压后就能用。 二、安装java环境 JMeter是基于Java开发的&#xff0c;运行JMeter需要Java环境。 1.下载JDK、安装Jdk 2.配置java环境变量 3.验证安装是否成功&#xff08;java -versio…

如何使用淘宝URL采集商品详情数据及销量

一、通过淘宝开放平台&#xff08;如果有资质&#xff09; 注册成为淘宝开发者 访问淘宝开放平台官方网站&#xff0c;按照要求填写开发者信息&#xff0c;包括企业或个人身份验证等步骤。这一步是为了获取合法的 API 使用权限。 了解商品详情 API 淘宝开放平台提供了一系列…

Unity3D中的Lua、ILRuntime与HybridCLR/huatuo热更对比分析详解

前言 在游戏开发中&#xff0c;热更新技术是一项重要的功能&#xff0c;它允许开发者在不重新发布游戏客户端的情况下&#xff0c;更新游戏内容。Unity3D作为广泛使用的游戏引擎&#xff0c;支持多种热更新方案&#xff0c;包括Lua、ILRuntime和HybridCLR/huatuo。本文将详细介…

QT加载Ui文件信息方法(python)

在 PyQt 或 PySide 中&#xff0c;加载 Qt Designer 生成的 .ui 文件有两种常见方法&#xff1a; 使用 pyuic 将 .ui 文件转换为 Python 代码。动态加载 .ui 文件。 以下是两种方法的详细说明和示例代码。 方法 1&#xff1a;使用 pyuic 将 .ui 文件转换为 Python 代码 步骤…

javascript基础从小白到高手系列一十二:JSON

本章内容  理解JSON 语法  解析JSON  JSON 序列化 正如上一章所说&#xff0c;XML 曾经一度成为互联网上传输数据的事实标准。第一代Web 服务很大程度上 是以XML 为基础的&#xff0c;以服务器间通信为主要特征。可是&#xff0c;XML 也并非没有批评者。有的人认为XML 过…

网络编程 - - TCP套接字通信及编程实现

概述 TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是一种面向连接的、可靠的传输层协议。在网络编程中&#xff0c;TCP常用于实现客户端和服务器之间的可靠数据传输。本文将基于C语言实现TCP服务端和客户端建立通信的过程。 三次握手 在…