{"id":655,"date":"2023-04-16T17:31:40","date_gmt":"2023-04-16T09:31:40","guid":{"rendered":"http:\/\/120.55.184.7\/?p=655"},"modified":"2025-07-14T15:31:21","modified_gmt":"2025-07-14T07:31:21","slug":"%e5%9f%ba%e4%ba%8ekcp%e7%9a%84%e5%b8%a7%e5%90%8c%e6%ad%a5%e6%9c%8d%e5%8a%a1%e5%99%a8%e5%ae%9e%e7%8e%b0","status":"publish","type":"post","link":"https:\/\/beijian99.top\/?p=655","title":{"rendered":"\u57fa\u4e8eKCP\u7684\u5e27\u540c\u6b65\u670d\u52a1\u5668\u5b9e\u73b0"},"content":{"rendered":"\n<p>\u524d\u7f6e\u77e5\u8bc6\u94fe\u63a5\uff1a<\/p>\n\n\n\n<p><a href=\"https:\/\/beijian99.top\/?p=656\" data-type=\"post\" data-id=\"656\" target=\"_blank\" rel=\"noreferrer noopener\">\u4ec0\u4e48\u662fKCP\uff1f<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/beijian99.top\/?p=653\" data-type=\"post\" data-id=\"653\" target=\"_blank\" rel=\"noreferrer noopener\">\u4ec0\u4e48\u662f\u5e27\u540c\u6b65\uff1f<\/a><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><strong>\u4ee5\u4e0b\u662f go \u4ee3\u7801\u5b9e\u73b0<\/strong><\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>1. \u57fa\u7840KCP\u670d\u52a1\u7aef\u521d\u59cb\u5316<\/strong><\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: go; title: ; notranslate\" title=\"\">\npackage main\n\nimport (\n    &quot;github.com\/xtaci\/kcp-go\/v5&quot;\n    &quot;golang.org\/x\/crypto\/pbkdf2&quot;\n    &quot;crypto\/sha1&quot;\n    &quot;log&quot;\n    &quot;time&quot;\n)\n\nfunc main() {\n    \/\/ KCP\u52a0\u5bc6\u914d\u7f6e\uff08\u53ef\u9009\uff09\n    key := pbkdf2.Key(&#x5B;]byte(&quot;demo_pass&quot;), &#x5B;]byte(&quot;demo_salt&quot;), 1024, 32, sha1.New)\n    block, _ := kcp.NewAESBlockCrypt(key)\n\n    \/\/ \u542f\u52a8KCP\u670d\u52a1\u7aef\u76d1\u542c\n    listener, err := kcp.ListenWithOptions(&quot;:8888&quot;, block, 10, 3)\n    if err != nil {\n        log.Fatal(err)\n    }\n    log.Println(&quot;\u5e27\u540c\u6b65\u670d\u52a1\u7aef\u5df2\u542f\u52a8\uff0c\u76d1\u542c\u7aef\u53e38888&quot;)\n\n    \/\/ \u5e27\u540c\u6b65\u4e3b\u5faa\u73af\u7ba1\u7406\n    go frameLoop()\n\n    for {\n        conn, err := listener.AcceptKCP()\n        if err != nil {\n            log.Println(&quot;\u5ba2\u6237\u7aef\u8fde\u63a5\u5931\u8d25:&quot;, err)\n            continue\n        }\n        go handleClient(conn)\n    }\n}\n<\/pre><\/div>\n\n\n<p><strong>\u5173\u952e\u70b9<\/strong>\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u4f7f\u7528<code>kcp.ListenWithOptions<\/code>\u521d\u59cb\u5316\u670d\u52a1\u7aef\uff0c\u652f\u6301\u52a0\u5bc6\u548cFEC\u7ea0\u9519\u3002<\/li>\n\n\n\n<li><code>10<\/code>\u548c<code>3<\/code>\u53c2\u6570\u5206\u522b\u4ee3\u8868\u6570\u636e\u5206\u7247\u548c\u7ea0\u9519\u5206\u7247\u6570\u91cf\uff0c\u63d0\u5347\u6297\u4e22\u5305\u80fd\u529b\u3002<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>2. \u5ba2\u6237\u7aef\u8fde\u63a5\u7ba1\u7406<\/strong><\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: go; title: ; notranslate\" title=\"\">\ntype ClientSession struct {\n    conn     *kcp.UDPSession\n    lastFrame uint32\n    inputQueue &#x5B;]&#x5B;]byte \/\/ \u5b58\u50a8\u5ba2\u6237\u7aef\u64cd\u4f5c\u6307\u4ee4\n}\n\nvar clients sync.Map \/\/ \u5168\u5c40\u5ba2\u6237\u7aef\u4f1a\u8bdd\u6620\u5c04\n\nfunc handleClient(conn *kcp.UDPSession) {\n    session := &amp;ClientSession{\n        conn: conn,\n    }\n    clients.Store(conn.RemoteAddr(), session)\n\n    \/\/ \u8bbe\u7f6eKCP\u53c2\u6570\u4f18\u5316\u5ef6\u8fdf\n    conn.SetNoDelay(1, 10, 2, 1) \/\/ \u5feb\u901f\u6a21\u5f0f\n    conn.SetWindowSize(4096, 4096)\n\n    buf := make(&#x5B;]byte, 4096)\n    for {\n        n, err := conn.Read(buf)\n        if err != nil {\n            clients.Delete(conn.RemoteAddr())\n            return\n        }\n        \/\/ \u6536\u96c6\u5ba2\u6237\u7aef\u8f93\u5165\uff08\u5982\u79fb\u52a8\u3001\u653b\u51fb\u6307\u4ee4\uff09\n        session.inputQueue = append(session.inputQueue, buf&#x5B;:n])\n    }\n}\n<\/pre><\/div>\n\n\n<p><strong>\u5173\u952e\u70b9<\/strong>\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u4f7f\u7528<code>SetNoDelay(1,10,2,1)<\/code>\u5f00\u542fKCP\u5feb\u901f\u6a21\u5f0f\uff0c\u964d\u4f4eRTO\u91cd\u4f20\u5ef6\u8fdf\u3002<\/li>\n\n\n\n<li>\u6bcf\u4e2a\u5ba2\u6237\u7aef\u7ef4\u62a4\u8f93\u5165\u961f\u5217\uff0c\u786e\u4fdd\u5e27\u540c\u6b65\u65f6\u6309\u987a\u5e8f\u5904\u7406\u3002<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>3. \u5e27\u540c\u6b65\u4e3b\u5faa\u73af<\/strong><\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: go; title: ; notranslate\" title=\"\">\nfunc frameLoop() {\n    ticker := time.NewTicker(33 * time.Millisecond) \/\/ 30\u5e27\/\u79d2\n    defer ticker.Stop()\n    var currentFrame uint32 = 0\n\n    for range ticker.C {\n        currentFrame++\n        var frameData &#x5B;]&#x5B;]byte\n\n        \/\/ \u6536\u96c6\u6240\u6709\u5ba2\u6237\u7aef\u5f53\u524d\u5e27\u8f93\u5165\n        clients.Range(func(_, value interface{}) bool {\n            session := value.(*ClientSession)\n            if len(session.inputQueue) &gt; 0 {\n                input := session.inputQueue&#x5B;0]\n                frameData = append(frameData, input)\n                session.inputQueue = session.inputQueue&#x5B;1:]\n            }\n            return true\n        })\n\n        \/\/ \u5e7f\u64ad\u5e27\u6570\u636e\uff08\u5305\u542b\u5f53\u524d\u5e27\u53f7+\u6240\u6709\u64cd\u4f5c\uff09\n        broadcastFrame(currentFrame, frameData)\n    }\n}\n\nfunc broadcastFrame(frame uint32, data &#x5B;]&#x5B;]byte) {\n    \/\/ \u5c01\u88c5\u5e27\u6570\u636e\uff08Protobuf\/JSON\uff09\n    payload := encodeFrameData(frame, data)\n\n    \/\/ \u5411\u6240\u6709\u5ba2\u6237\u7aef\u53d1\u9001\n    clients.Range(func(_, value interface{}) bool {\n        session := value.(*ClientSession)\n        if _, err := session.conn.Write(payload); err != nil {\n            log.Println(&quot;\u5e7f\u64ad\u5931\u8d25:&quot;, err)\n        }\n        return true\n    })\n}\n<\/pre><\/div>\n\n\n<p><strong>\u5173\u952e\u70b9<\/strong>\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u56fa\u5b9a\u65f6\u95f4\u95f4\u9694\uff08\u598233ms\uff09\u9a71\u52a8\u5e27\u540c\u6b65\uff0c\u786e\u4fdd\u6240\u6709\u5ba2\u6237\u7aef\u903b\u8f91\u5e27\u4e00\u81f4\u3002<\/li>\n\n\n\n<li>\u4f7f\u7528<code>encodeFrameData<\/code>\u5e8f\u5217\u5316\u5e27\u6570\u636e\uff0c\u63a8\u8350Protobuf\u51cf\u5c11\u5e26\u5bbd\u5360\u7528\u3002<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>4. \u65ad\u7ebf\u91cd\u8fde\u4e0e\u72b6\u6001\u5feb\u7167<\/strong><\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: go; title: ; notranslate\" title=\"\">\n\/\/ \u5ba2\u6237\u7aef\u91cd\u8fde\u65f6\u53d1\u9001\u5b8c\u6574\u72b6\u6001\nfunc handleReconnect(session *ClientSession) {\n    snapshot := getWorldSnapshot() \/\/ \u83b7\u53d6\u5f53\u524d\u6e38\u620f\u72b6\u6001\u5feb\u7167\n    if _, err := session.conn.Write(snapshot); err != nil {\n        log.Println(&quot;\u5feb\u7167\u53d1\u9001\u5931\u8d25:&quot;, err)\n    }\n}\n<\/pre><\/div>\n\n\n<p><strong>\u5173\u952e\u70b9<\/strong>\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u65ad\u7ebf\u91cd\u8fde\u65f6\u901a\u8fc7<code>getWorldSnapshot<\/code>\u751f\u6210\u5168\u91cf\u72b6\u6001\uff0c\u907f\u514d\u9010\u5e27\u8ffd\u8865\u3002<\/li>\n\n\n\n<li>KCP\u7684\u53ef\u9760\u4f20\u8f93\u786e\u4fdd\u5feb\u7167\u6570\u636e\u5b8c\u6574\u5230\u8fbe\u3002<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>5. \u6027\u80fd\u4f18\u5316\u5efa\u8bae<\/strong><\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>KCP\u53c2\u6570\u8c03\u4f18<\/strong>\uff1a<br>\u2022 <code>conn.SetMtu(1350)<\/code>\uff1a\u907f\u514dIP\u5206\u7247\uff0c\u9002\u914d\u5e38\u89c1\u7f51\u7edcMTU\u3002<br>\u2022 <code>conn.SetStreamMode(true)<\/code>\uff1a\u6d41\u6a21\u5f0f\u51cf\u5c11\u5206\u7247\u5f00\u9500\u3002<\/li>\n\n\n\n<li><strong>\u5e26\u5bbd\u63a7\u5236<\/strong>\uff1a<br>\u2022 \u4f7f\u7528<code>conn.SetWindowSize(1024, 1024)<\/code>\u9650\u5236\u53d1\u9001\/\u63a5\u6536\u7a97\u53e3\uff0c\u9632\u6b62\u5185\u5b58\u66b4\u6da8\u3002<\/li>\n\n\n\n<li><strong>\u52a0\u5bc6\u4e0e\u538b\u7f29<\/strong>\uff1a<br>\u2022 \u96c6\u6210Snappy\u538b\u7f29\u7b97\u6cd5\u51cf\u5c11\u5e27\u6570\u636e\u5927\u5c0f\u3002<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n","protected":false},"excerpt":{"rendered":"<p>\u524d\u7f6e\u77e5\u8bc6\u94fe\u63a5\uff1a \u4ec0\u4e48\u662fKCP\uff1f \u4ec0\u4e48\u662f\u5e27\u540c\u6b65\uff1f \u4ee5\u4e0b\u662f go \u4ee3\u7801\u5b9e\u73b0 1. \u57fa\u7840KCP\u670d\u52a1\u7aef\u521d\u59cb\u5316 \u5173\u952e\u70b9\uff1a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[131],"tags":[134,132],"class_list":["post-655","post","type-post","status-publish","format-standard","hentry","category-131","tag-kcp","tag-132"],"_links":{"self":[{"href":"https:\/\/beijian99.top\/index.php?rest_route=\/wp\/v2\/posts\/655","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/beijian99.top\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/beijian99.top\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/beijian99.top\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/beijian99.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=655"}],"version-history":[{"count":3,"href":"https:\/\/beijian99.top\/index.php?rest_route=\/wp\/v2\/posts\/655\/revisions"}],"predecessor-version":[{"id":1149,"href":"https:\/\/beijian99.top\/index.php?rest_route=\/wp\/v2\/posts\/655\/revisions\/1149"}],"wp:attachment":[{"href":"https:\/\/beijian99.top\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=655"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/beijian99.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=655"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/beijian99.top\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=655"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}