TCP协议之校验和 ( js实现"1的补码和"、"校验和"的求解 )
参考:
https://baike.baidu.com/item/%E6%A0%A1%E9%AA%8C%E5%92%8C/7358071?fr=aladdin
https://www.jianshu.com/p/56576cb4cca9
发送方生成校验和:
1.将待发送数据分成若干个16位的位串,每个位串看成一个二进制数,这里并不管位串代表什么,可以是整数、浮点数、或者位图;
2.将IP、UDP、TCP的PDU首部中的校验和字段置为0,该字段也参与校验和运算;
3.对这些16位的二进制数进行1的补码和运算,累加的结果再取反码即生成了校验码,将校验码放入校验和字段中。
(其中1的补码和运算,即带循环进位的加法,最高位有进位则循环进到最低位;反码即二进制各位取反,如0111的反码为1000。)
接收方校验校验和:
1.接收方将接收的数据(包括校验和字段)按发送方同样的方法进行1的补码和运算,累加的结果再取反码;
2.校验,如果上步的结果为0,表示传输正确;否则传输出错。
校验算法示例如图:

图中所示为一个只包含4个16位二进制数进行检验和运算的简单例子。图(a)所示为发送方的运算,①、②、③是3个数据,④是检验和,先置0,也参加检验和运算。⑤是它们的一的补码和,⑥是⑤的反码。发送方将⑥放到检验和字段和数据一起发出。图(b)所示为接收方的运算,如果没有传输差错,最后结果应为0。
附注:
进制转换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | function numTransfer(numStr = '0' , ori = 10, to = 2) { if ( typeof ori !== 'number' || ori < 2 || ori > 36) { throw new Error( '元数据进制错误' ) } if ( typeof to !== 'number' || to < 2 || to > 36) { throw new Error( '数据进制错误' ) } if ( typeof numStr !== 'string' || !numStr || !/^[0-9a-z]+$/.test(numStr)) { throw new Error( '元数据格式错误' ) } const max = numStr.split( '' ).sort().reverse()[0] if (parseInt(max, 36) >= ori) { throw new Error( '元数据格式错误' ) } return parseInt(numStr, ori).toString(to) } |
"1的补码和"、"校验和"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | function generateChecksum() { const dataList = Array.from(arguments) if (dataList.length === 0) return ; let maxLen = 0, dataSum = 0; for ( let data of dataList) { if (!( typeof data === 'string' && /^[01]+$/.test(data))) { throw new Error(`格式错误: ${data}`) } else { const len = data.length if (len > maxLen) maxLen = len; dataSum += (+numTransfer(data, 2, 10)); } } let dataSumBinStr = numTransfer(String(dataSum), 10, 2) function reduce(binStr, len) { const binStrLen = binStr.length if (binStrLen > len) { const num = binStrLen - len const sum = (+numTransfer(binStr.slice(0, num), 2, 10)) + (+numTransfer(binStr.slice(num), 2, 10)) const nexBinStr = numTransfer(String(sum), 10, 2) return reduce(nexBinStr, len) } else { return binStr } } let compSumStr = reduce(dataSumBinStr, maxLen) const compSumStrLen = compSumStr.length if (compSumStrLen < maxLen) { const arr = compSumStr.split( '' ) for ( let i = 0; i < maxLen - compSumStrLen; i++) arr.unshift( '0' ); compSumStr = arr.join( '' ) } const checksumStr = compSumStr.split( '' ).map(i => i === '0' ? '1' : '0' ).join( '' ) return { compSumStr, checksumStr } } |
执行示例:
generateChecksum('111111', '100') // {compSumStr: '000100', checksumStr: '111011'}
generateChecksum('111111', '100', '111011') // {compSumStr: '111111', checksumStr: '000000'}
----------- 赠人玫瑰,手有余香 如果本文对您有所帮助,动动手指扫一扫哟 么么哒 -----------
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)