网络请求
在日常的游戏开发或者软件开发中,大家基本都会使用到或者了解到Http请求或者Socket请求。最常见就是http请求。只要你是C/S架构或者B/S架构的软件,你基本上就会接触到网络请求。
在游戏软件中基本会将游戏场景分为:强联网场景和弱联网场景。我们下面以这两个场景进行展开讲述所用到的技术点以及该如何使用他们。
联网场景简介
弱联网场景
弱联网场景基本上是对于游戏状态而言的。大部分单机游戏基本上都是弱联网游戏。
对于这类游戏而言,联网的场景一般就是属于登录,购买,存档。 需要什么状态或者信息就直接从服务器获取或者更改即可。通讯方式基本上为一来一回。
部分卡牌游戏也会采用弱联网的方式进行交互,一定时间轮询房间内的状态,然后在客户端表现出来。
这类场景基本上都会直接使用Http请求或者是简单的RPC请求进行交互。同时服务端也会尽量设计为无状态服务,方便横向扩展。
强联网场景
强联网游戏基本上你不连接网络就玩不了了,或者当你网络不好的时候得到的体验就相当的差。
一般玩家之间对战,聊天服务这类的游戏都是强联网的场景,即时性要求较高。并且并不是一来一回的请求模式,服务端可以主动推送信息给不同的客户端,不需要等待客户端主动查询状态。
这类场景基本都是直接使用基础通讯进行交互,视情况而言会使用TCP,UDP或者KCP,以及基于http升级的Websocket协议。
协议和基础应用
大部分的地方都有Http的协议介绍,这了就不赘述了。
我们直接开门见山介绍一下客户端以及服务端的用法和代码样例。
Unity发起Http请求
从Unity 2017开始中基本会使用 UnityWebRequest
进行网络请求 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class HttpDemo : MonoBehaviour { public string url; void Start() { url = "http://127.0.0.1:3001/"; StartCoroutine(Get()); } IEnumerator Get() { UnityWebRequest webRequest = new UnityWebRequest(url,UnityWebRequest.kHttpVerbGET); webRequest.downloadHandler = new DownloadHandlerBuffer(); yield return webRequest.SendWebRequest(); if(webRequest.isNetworkError || webRequest.isHttpError) { Debug.Log(webRequest.error); } byte[] results = webRequest.downloadHandler.data; } }
C#
|
我们来简单讲解下这段代码:
主要看 Get() 方法:
UnityWebRequest webRequest = new UnityWebRequest(url,UnityWebRequest.kHttpVerbGET);
- 初始化 webRequest.downloadHandler ,不然返回后会为空。
webRequest.downloadHandler = new DownloadHandlerBuffer();
Golang 提供Http服务器
使用Golang起一个Http服务器很简单:
1 2 3 4 5 6 7 8 9 10 11 12
| func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello") }) s := &http.Server{ Addr: ":3001", ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, MaxHeaderBytes: 1 << 20, } log.Fatal(s.ListenAndServe()) }
TCL
|
我们来简单讲解一下下面的代码:
1 2 3
| http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello") })
REASONML
|
1 2 3 4 5 6
| s := &http.Server{ Addr: ":3001", ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, MaxHeaderBytes: 1 << 20, }
DTS
|
1
| log.Fatal(s.ListenAndServe())
REASONML
|
长链接
在长链接里,一般会使用TCP,UDP或者KCP,以及基于http升级的Websocket协议。这几种协议的具体差别很多地方都有。
这里以TCP为例子讲解如何进行TCP链接的使用。
Echo 程序
Echo程序是网络编程中最基础的案例。建立网络连接后,客户端向服务端发送一行文本,服务端收到后将文本发送回客户端,其实就是最简单版的一来一回的请求代码:
我们需要自己实现以下几步:
- 建立链接
- 发送消息
- 接受并且回显消息
- 关闭链接
Unity 长链接实现
搭建UI面板
这里我们会第一次接触Unity的脚本编程。可以先简单跟着做就行,这里涉及到的东西在后续的章节会进行详细解说。
首先让我们知道我们想要哪些东西:
- 需要2个按键
- 一个发送信息的输入框
- 一个接受信息回显的输出框
确定我们需要这些以后,开始使用Unity进行开发:
- 创建Unity项目后,在 Hierarchy 栏右键点击鼠标创建UI:

分别创建两个Button,一个InputField,还有一个Text,并且根据用途进行重命名。

点击运行后,最后呈现出是这样的:

脚本编写
UI面板简单拼接后,我们进行脚本编写:
在Unity中需要使用 Net.Sockets
包进行Sockets网络开发。
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 38 39 40 41 42 43 44 45 46
| public class Echo:MonoBehaviour { Socket socket; public InputField InputFeld; public Text text; public string host; public int port; public void Start() { host = "127.0.0.1"; port = 8972; } public void Connection() { socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp); socket.Connect(host, port); } public void Send() { string sendStr = InputFeld.text; byte[] sendBytes = System.Text.Encoding.Default.GetBytes(sendStr); socket.Send(sendBytes); byte[] readBuff = new byte[1024]; int count = socket.Receive(readBuff); string recvStr = System.Text.Encoding.Default.GetString(readBuff, 0, count); text.text = recvStr; socket.Close(); } }
CSHARP
|
挂载脚本
- 我们将这个脚本绑定(直接将脚本拖动过去)在
Main Camera
上就会发现这里多了个我们写完的Echo脚本,并且多了两个需要挂载的组件,这就是我们在脚本定义的两个组件:


- 接下来我们需要绑定点击事件。在创建的Button里找到Button栏
- 在OnClick中绑定之前挂载脚本的 MainCamera组件的Echo.Send方法。

Golang 服务端代码
在编写服务端代码时,基本就是代码的问题了。下面的代码每一句都会有注释,可以详细看看:
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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| package main
import ( "log" "net" )
func main() { ln, err := net.Listen("tcp", ":8972") if err != nil { panic(err) } var connections []net.Conn defer func() { for _, conn := range connections { conn.Close() } }() for { conn, e := ln.Accept() if e != nil { if ne, ok := e.(net.Error); ok && ne.Timeout() { log.Printf("accept temp err: %v", ne) continue } log.Printf("accept err: %v", e) return } go handleConn(conn) connections = append(connections, conn) if len(connections)%100 == 0 { log.Printf("total number of connections: %v", len(connections)) } } }
func handleConn(conn net.Conn) { c := NewClient(conn) go c.Echo() }
type Client struct { net.Conn }
func NewClient(conn net.Conn) *Client { return &Client{conn} }
func (c Client) Echo() { buf := make([]byte, 1024) for { c.Read(buf) c.Write(buf) } }
GO
|
到此,双端的代码就编写完毕。你可以先运行服务端代码,然后运行Unity代码,之后就可以进行测试这个Echo程序了。
总结
至此,我们简单的介绍了一下Unity和Golang如何通过Http和Tcp进行通讯。在一个网络游戏里,会有使用Http的场景,也会有使用Tcp或者其他协议的Socket流的场景,所以这些我们都应该要掌握一下。
下一章,我们会进行一个基于Unity的聊天室开发。Show Code ,No BB。