Unity BestHTTP 文档翻译(二)

WebSocket

我们可以通过WebSocket类使用WebSocket功能,只需要将服务器的Uri传递给WebSocket的构造函数即可:

void WebSocket()
{
    WebSocket webSocket = new WebSocket(new Uri("wss://html5labs-interop.cloudapp.net/echo"));
    //webSocket.OnOpen...
    //注册事件之后,我们就可以开始连接
    webSocket.Open();
    //在这一步之后,我们将收到一个OnOpen事件,我们可以开始发送消息到服务器
    webSocket.Send("Message to the Server");
    byte[] buffer = new byte[1024];
    webSocket.Send(buffer);
    //所有通信完成之后,就关闭连接
    webSocket.Close();
}

在这一步之后,我们可以注册我们的事件处理程序来处理这几个事件:
OnOpen事件:建立与服务器的连接时调用。 在此事件之后,WebSocket的IsOpen属性将为True,直到我们或服务器关闭连接或发生错误
OnMessage事件:当从服务器收到文本消息时调用
OnBinary事件: 当从服务器收到二进制信息时调用
OnClosed事件:当客户端或服务器关闭连接或发生内部错误时调用。
当客户端通过关闭功能关闭连接时,它可以提供一个代码和一个消息,指出关闭的原因。服务器通常会回应我们的代码和消息。
OnError事件:当我们无法连接到服务器时发生内部错误或连接丢失时调用。第二个参数是一个Exception对象,但它可以为null
OnErrorDesc事件:OnError是一个更具信息性的事件,因为后者仅通过Exception参数调用。 此事件在OnError事件之后调用,但它可以提供更详细的错误报告。
OnIncompleteFrame 事件: 在下面的Advanced Websocket中有介绍

Advanced WebSocket

Ping消息:通过在收到OnOpen事件之前将StartPingThread属性设置为True,可以启动一个新线程以将Ping消息发送 到服务器。这样Ping消息将定期发送到服务器,两次Ping之间的延迟可以在PingFrequency属性中设置(默认值为1000ms)。
Pong消息:从服务器接收到的所有ping消息都会自动生成Pong应答
Streaming:过长的文本或二进制信息将被分割。 这些片段默认由插件自动组装。
如果我们向WebSocket的OnIncompleteFrame事件注册事件处理程序,则可以覆盖此机制。
每次客户端收到不完整的片段时都会调用此事件。 这些片段将被插件忽略,它不会尝试组装这些片段或将它们存储起来。 此事件可用于实现流式传输体验。

Socket.IO

Socket.IO实现使用插件已具有的功能
它将发送HTTPRequests来获取握手数据,当轮询传输使用其所有功能(cookie,连接重用等)时发送和接收数据包。 WebSocket实现用于WebSocket传输。
这个Socket.IO实现的简单功能列表:
易于使用和熟悉的API
兼容最新的Socket.IO规范
从轮询传输到websocket传输的无缝升级
断开时自动重新连接
简单高效的二进制数据发送和多种方式的接收
在高级模式下使用它的强大工具(切换默认编码器,禁用自动解码等)
如果你想连接到一个Socket.IO服务,你可以使用BestHTTP.SocketIO.SocketManager类来完成。
首先你必须创建一个SocketManager实例:
var manager = new SocketManager(new Uri(“http://chat.socket.io/socket.io/“));
url中的/socket.io/路径非常重要,默认情况下,Socket.IO服务器将监听此查询。 所以不要忘记把它也加到你的测试网址上

Connecting to namespaces

void ConnectingToNamespaces()
{
    SocketManager manager = new SocketManager(new Uri("http://chat.socket.io/socket.io/"));
    //默认情况下,SocketManager将在连接到服务器时连接到根(“/”)名称空间。 你可以通过SocketManager的Socket属性来访问它:
    Socket root = manager.Socket;
    //可以通过GetSocket(“/ nspName”)函数或通过管理器的索引器属性访问非默认名称空间:
    Socket nsp1 = manager["/customNamespace"];
    Socket nsp2 = manager.GetSocket("/customNamespace");
    //首次访问命名空间将会启动内部连接程序
}

Subscribing and receiving events

//您可以订阅预定义和自定义事件
void SubscribingAndReceivingEvents()
{
    SocketManager manager = new SocketManager(new Uri("http://chat.socket.io/socket.io/"));

    //预定义事件
    //connect:当命名空间打开时发送
    //connecting:当SocketManager开始连接到socket.io服务器时发送
    //event:根据自定义(程序员定义的)事件发送
    //disconnect:在传输断开时,SocketManager关闭,Socket关闭或在握手数据中指定的给定时间内未收到服务器的Pong消息时发送
    //reconnect:插件成功重新连接到socket.io服务器时发送
    //reconnecting:当插件尝试重新连接到socket.io服务器时发送
    //reconnect_attempt:当插件尝试重新连接到socket.io服务器时发送
    //reconnect_failed:当重新连接尝试无法连接到服务器并且ReconnectAttempt达到选项'ReconnectionAttempts'值时发送
    //error:发送到服务器或内部插件错误。 该事件的唯一参数将是一个BestHTTP.SocketIO.Error对象

    //自定义事件
    //自定义事件是程序员定义的事件,您的服务器将发送给您的客户端。 您可以通过调用套接字的On函数来订阅事件
    manager.Socket.On("login", (socket, packet, args) => { });
    //socket参数将是服务器发送此事件的名称空间套接字对象。 
    //packet参数包含事件的内部数据包数据。 该数据包可用于访问服务器发送的二进制数据,或使用定制的Json解析器库来解码有效载荷数据
    //args参数是一个可变长度数组,它包含来自数据包有效负载数据的已解码对象。
    //使用默认的Json编码器,这些参数可以是对象的“原始”类型(int,double,string)或对象列表(List <object>)或Dictionary <string,object>

    //服务器上发出的消息
    //socket.emit('message', ‘MyNick’, ‘Msg to the client’); 
    //客户端捕获的消息
    //订阅message事件
    manager.Socket.On("message", (socket, packet, args) =>
    {
        Debug.Log(string.Format("Message from {0}: {1}", args[0], args[1]));
    });


    //其它与事件相关的功能
    //Once:你可以订阅一个仅调用一次的事件
    manager.Socket.Once("connect", (socket, packet, args) => { });
    //off:取消订阅
    manager.Socket.Off();//取消所有订阅的事件
    manager.Socket.Off("connect");//对事件"connect"取消订阅
    //manager.Socket.Off("connect", OnConnected); //从事件"connect"中移除OnConnected方法
}

Sending acknowledgement to the server

//向服务器发送确认 
void SendingAcknowledgement()
{
    SocketManager manager = new SocketManager(new Uri("http://chat.socket.io/socket.io/"));
    //您可以通过调用套接字的EmitAck函数向服务器发回确认
    //您必须传递原始数据包和可选数据:
    manager["/customNamespace"].On("customEvent", (socket, packet, args) =>
    {
        socket.EmitAck(packet, "Event", "Received", "Successfully");
    });
}

Sending binary data

void SendingBinaryData()
{
    SocketManager manager = new SocketManager(new Uri("http://chat.socket.io/socket.io/"));
    //有两种方式发送二进制数据
    //一.
    //通过Emit函数传递,插件将扫描参数,如果它找到一个参数,它会将其转换为二进制附件(如在Socket.IO 1.0中介绍的)。
    //这是最有效的方法,因为它不会将字节数组转换为客户端上的Base64编码字符串,并且在服务器端将其转换为二进制。
    byte[] data = new byte[10];
    manager.Socket.Emit("eventWithBinary", "textual param", data);
    //二.
    //如果二进制数据作为字段或属性嵌入对象中,则Json编码器必须支持该转换。 
    //默认的Json编码器不能将嵌入的二进制数据转换为Json,你必须使用更高级的Json解析器库(比如“JSON .NET for Unity” - http://u3d.as/5q2)
}

Receiving binary data

void ReceivingBinaryData()
{
    SocketManager manager = new SocketManager(new Uri("http://chat.socket.io/socket.io/"));
    //在Socket.IO服务器中,当二进制数据发送到客户端时,它将用Json对象({'_ placeholder':true,'num':xyz})替换数据,并将二进制数据发送到另一个数据包中
    //在客户端,这些数据包将被收集并合并为一个数据包
    //二进制数据将位于数据包的Attachments属性中
    //在这里你将有一些使用这个数据包的选择:
    //一、
    //在您的事件处理函数中,您可以通过数据包的Attachments属性访问所有二进制数据
    manager.Socket.On("frame", (socket, packet, args) =>
    {
        Texture2D texture2D = new Texture2D(0, 0);
        texture2D.LoadImage(packet.Attachments[0]);
    });
    //二、
    //第二个选项与前一个选项几乎相同,但有一点改进:我们不会将发送的Json字符串解码为c#对象
    //我们可以这样做,因为我们知道服务器只发送二进制数据,这个事件没有其他信息。 所以我们会让插件知道不要解码有效载荷:
    manager.Socket.On("frame", (socket, packet, args) =>
    {
        Texture2D texture2D = new Texture2D(0, 0);
        texture2D.LoadImage(packet.Attachments[0]);
    }, false);
    //三、
    //我们可以将“{'_placeholder':true,'num':xyz}”字符串替换为Attachments列表中Attachment的索引
    manager.Socket.On("frame", (socket, packet, args) =>
    {
        //用索引替换Json对象
        packet.ReconstructAttachmentAsIndex();
        //解码有效载荷到object[]
        args = packet.Decode(socket.Manager.Encoder);
        //现在args只包含一个索引号(可能是0)
        byte[] data = packet.Attachments[Convert.ToInt32(args[0])];

        Texture2D texture2D = new Texture2D(0, 0);
        texture2D.LoadImage(data);
    }, false);
}

Set the default Json encoder

//设置默认的Json编码器
//如果由于各种原因想要更改默认的Json编码器,首先必须编写一个新的Json编码器
//为此,您必须编写一个新的类,该类可以从BestHTTP.SocketIO.JsonEncoders命名空间实现IJsonEncoder
//剥离的IJsonEncoder非常小,你只需要实现两个功能:
public interface IJsonEncoder
{
    List<object> Decode(string json);
    string Encode(List<object> obj);
}
//Decode函数必须将给定的json字符串解码为对象列表。 由于Socket.IO协议的性质,发送的json是一个数组,第一个元素是事件的名称。

//编码功能用于对客户想要发送到服务器的数据进行编码
//该列表的结构与Decode相同:列表的第一个元素是事件的名称,其他任何元素都是用户发送的参数。

//下面是使用示例文件夹中的LitJson库的完整示例:
public sealed class LitJsonEncoder : IJsonEncoder
{
    public List<object> Decode(string json)
    {
        JsonReader reader = new JsonReader(json);
        return JsonMapper.ToObject<List<object>>(reader);
    }

    public string Encode(List<object> obj)
    {
        JsonWriter writer = new JsonWriter();
        JsonMapper.ToJson(obj, writer); return writer.ToString();
    }
}

AutoDecodePayload

已经在“Receiving binary data”中讨论过AutoDecodePayload,但是您不仅可以在每个事件中设置该值,套接字也可以
套接字具有AutoDecodePayload属性,该属性用作事件订阅的默认值
其默认值为true - 所有有效载荷都被解码并分派给事件订户。 如果设置为false,则插件不会执行解码,您必须自行完成解码。

你不想每次都施放参数:当然! 您可以在Socket对象上设置AutoDecodePayload,并且可以使用您最喜欢的Json解析器将数据包的有效负载解码为强类型对象
但请记住,有效负载将包含事件的名称,它是一个json数组。 示例有效内容如下所示:“['eventName',{'field':'stringValue'},{'field':1.0}]”

Error handling

//发生服务器端或客户端错误时发生的“error”事件
//事件的第一个参数将是一个Error对象。 这将包含Code属性中的错误代码和Message属性中的字符串消息
//ToString()函数在这个类中被覆盖,你可以使用这个函数写出它的内容。
void ErrorHandling()
{
    SocketManager manager = new SocketManager(new Uri("http://chat.socket.io/socket.io/"));
    manager.Socket.On(SocketIOEventTypes.Error, (socket, packet, args) =>
    {
        Error error = args[0] as Error;

        switch (error.Code)
        {
            case SocketIOErrors.User:
                Debug.Log("Exception in an event handler!");
                break;
            case SocketIOErrors.Internal:
                Debug.Log("Internal error!");
                break;
            default:
                Debug.Log("Server error!");
                break;
        }

        Debug.Log(error.ToString());
    });
}

Available options in the SocketOptions class

SocketOptions类中的可用选项
您可以将SocketOptions实例传递给SocketManager的构造函数

您可以更改以下选项:
Reconnection:断开连接后是否自动重新连接。它的默认值是true。
ReconnectionAttempts:放弃之前的尝试次数。它的默认值是Int.MaxValue
ReconnectionDelay:尝试重新连接之前最初等待多久。受+/- RandomizationFactor影响。例如,默认的初始延迟将在500毫秒到1500毫秒之间。其默认值是10000ms
ReconnectionDelayMax:重新连接之间等待的最长时间。如上所述,每次尝试都会增加重新连接延迟以及随机化。其默认值是5000ms
RandomizationFactor:它可以用来控制ReconnectionDelay范围。它的默认值是0.5,可以在0..1的值之间进行设置。
Timeout:发出“connect_error”和“connect_timeout”事件之前的连接超时。它不是底层的tcp套接字的连接超时,而是socket.io协议。它的默认值是20000ms
AutoConnect:通过将此设置为false,只要您决定适当,就必须调用SocketManager的Open()。
当你创建一个新的SocketOptions对象时,它的属性被设置为它们的默认值。

//SignalR(命名空间)
//ASP .NET SignalR 是一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信
//像Socket.IO这样使用插件的基本特性实现SignalR
//HTTPRequests和WebSockets用于连接和利用连接池进行通信
//Cookies随请求一起发送,记录器用于记录有关协议和错误的信息。
//SignalR实现的特性简要列表:
//与最新的SignalR服务器实现兼容
//易于使用的API
//传输回退
//重新连接逻辑
//支持所有集线器功能

The Connection class

//BestHTTP.SignalR命名空间中的Connection类管理到SignalR服务器的抽象连接
//连接到SignalR服务器从创建Connection对象开始
//该类将跟踪协议的当前状态并将触发事件
void TheConnectionClass()
{
    //你有多个途径创建一个连接对象
    Uri uri = new Uri("http://besthttpsignalr.azurewebsites.net/raw-connection/");
    //通过仅将服务器的URI传递给构造函数来创建连接,而不使用集线器
    Connection signlRConnection1 = new Connection(uri);
    //通过将集线器名称也传递给构造函数来创建连接,并使用集线器
    Connection signlRConnection2 = new Connection(uri, "hub1", "hub2", "hubN");
    //通过将Hub对象传递给构造函数来创建连接,并使用Hub
    //using BestHTTP.SignalR.Hubs;
    Hub hub1 = new Hub("hub1");
    Hub hub2 = new Hub("hub2");
    Hub hubN = new Hub("hubN");
    Connection signlRConnection3 = new Connection(uri, hub1, hub2, hubN);
    //在创建Connection之后,我们可以通过调用Open()函数来开始连接到服务器
    signlRConnection1.Open();
}

Handling general events

void HandlingGeneralEvents()
{
    Uri uri = new Uri("http://besthttpsignalr.azurewebsites.net/raw-connection/");
    Connection signlRConnection = new Connection(uri);
    //Connection类将允许您订阅多个事件,这些事件如下:
    //OnConnected:当connection类成功连接并且SignalR协议用于通信时,会触发此事件
    signlRConnection.OnConnected += (con) => Debug.Log("Connected to the SignalR server!");
    //OnClosed:当SignalR协议关闭时会触发此事件,并且不再发送或接收更多消息
    signlRConnection.OnClosed += (con) => Debug.Log("Connection Closed");
    //OnError:发生错误时调用。 如果连接已经打开,插件将尝试重新连接,否则连接将被关闭
    signlRConnection.OnError += (con, err) => Debug.Log("Error: " + err);
    //OnReconnecting:当重新连接尝试开始时,将触发此事件
    //在此事件之后,将调用OnError或OnReconnected事件
    //在OnReconnected / OnClosed事件之前可以触发多个OnReconnecting-OnError事件对,因为插件会在给定的时间内尝试重新连接多次。
    signlRConnection.OnReconnecting += (con) => Debug.Log("Reconnecting");
    //OnReconnected:重新连接尝试成功时触发
    signlRConnection.OnReconnecting += (con) => Debug.Log("Reconnected");
    //OnStateChnaged:连接状态改变时触发,事件处理程序将收到旧状态和新状态
    signlRConnection.OnStateChanged += (conn, oldState, newState) => Debug.Log(string.Format("State Changed {0} -> {1}", oldState, newState));
    //OnNonHubMessage:服务器向客户端发送非集线器消息时触发
    //客户端应该知道服务器期望的消息类型,并且应该相应地转换接收到的对象
    signlRConnection.OnNonHubMessage += (con, data) => Debug.Log("Message from server: " + data.ToString());
    //RequestPreparator:每个HTTPRequest都会调用这个委托并将发送到服务器, 它可以用来进一步自定义请求
    signlRConnection.RequestPreparator = (con, req, type) => req.Timeout = TimeSpan.FromSeconds(30);
}

Sending non-Hub messages

void SendingNonHubMessages()
{
    Uri uri = new Uri("http://besthttpsignalr.azurewebsites.net/raw-connection/");
    Connection signlRConnection = new Connection(uri);
    //发送非集线器消息到服务器像在connection对象上调用一个函数一样容易:
    signlRConnection.Send(new { Type = "Broadcast", Value = "Hello SignalR World!" });
    //此函数将使用Connection的JsonEncoder将给定对象编码为Json字符串,并将其发送到服务器
    //已编码的Json字符串可以使用SendJson函数发送:
    signlRConnection.SendJson("{ Type: ‘Broadcast’, Value: ‘Hello SignalR World!’ }");
}

Hubs

//为了定义客户端上Hub可以从服务器调用的方法,并在服务器上调用Hub上的方法,必须将Hubs添加到Connection对象中
//这可以通过将集线器名称或集线器实例添加到Connection构造函数中完成,在Connection Class部分中已进行演示
//using BestHTTP.SignalR.Messages;
void Hubs()
{
    Uri uri = new Uri("http://besthttpsignalr.azurewebsites.net/raw-connection/");
    Connection signalRConnection = new Connection(uri);
    //Accessing hubs (访问集线器)
    Hub hub1 = signalRConnection[0];
    Hub hub2 = signalRConnection["hubName"];
    //Register server callable methods(注册服务器可调用方法)
    //要处理服务器可调用方法的调用,我们必须调用集线器的On函数:
    signalRConnection["hubName"].On("joined", (hub, msg) =>
    {
        Debug.Log(string.Format("{0} joined at {1}", msg.Arguments[0], msg.Arguments[1]));
    });

    //On的第二个参数类型是MethodCallMessage
    //MethodCallMessage是一个服务器发送的对象,它包含以下属性:
    //Hub:包含该方法必须调用的集线器名称的字符串
    //Method:包含方法名称的字符串
    //Arguments:包含方法调用参数的对象数组。 它可以是一个空数组
    //State:包含其他自定义数据的字典。

    //该插件将使用Hub和Method属性将消息发送到正确的集线器和事件处理程序。 处理方法调用的函数只能使用参数和状态属性

    //Call server-side methods (调用服务端方法)
    //调用服务器端方法可以通过调用Hub的Call函数来完成
    //重载的调用函数能够满足每个需求
    //Call函数是非阻塞函数,它们不会阻塞,直到服务器发送有关该呼叫的任何消息
    //重载如下:
    //Call(string method, params object[] args): 
    //这可用于以fireand -forget样式调用服务器端函数
    //我们不会收到有关方法调用成功或失败的消息。 这个函数可以在没有任何'args'参数的情况下调用,以调用无参数方法
    signalRConnection["hubName"].Call("Ping");
    signalRConnection["hubName"].Call("Message", "param1", "param2");
    //Call(string method, OnMethodResultDelegate onResult, params object[] args): 
    //该函数可以作为前一个函数使用,但函数可以传递第二个参数,该函数将在服务器端函数成功调用时调用。
    signalRConnection["hubName"].Call("GetValue", OnGetValueDone);
    //此回调函数接收调用此函数的Hub,发送给服务器的原始ClientMessage消息以及由服务器作为该方法调用结果发送的ResultMessage实例
    //ResultMessage对象包含一个ReturnValue和一个State属性。

    //如果方法的返回类型为void,则ReturnValue为null
    //Call(string method, OnMethodResultDelegate onResult, OnMethodFailedDelegate onError, params object[] args):
    //此函数可指定当方法在服务器上运行失败时调用的回调。 没有找到方法,参数错误或未处理的异常,在方法调用时都可能会引发故障
    signalRConnection["hubName"].Call("GetValue",
    OnGetValueDone,
    OnGetValueFailed);
    //FailureMessage包含以下属性:
    //IsHubError:如果是Hub错误,则为True
    //ErrorMessage:关于错误本身的简短消息
    //StackTrace:如果服务器上打开了详细的错误报告,那么它将包含错误的堆栈跟踪
    //AdditionalData:如果不为空,则它包含有关错误的其他信息


    // Call(string method, OnMethodResultDelegate onResult, OnMethodFailedDelegate onError, OnMethodProgressDelegate onProgress, params object[] args): 
    //该函数可用于向服务器端方法调用添加额外的进度消息处理程序。 对于长时间运行的作业,服务器可以向客户端发送进度消息
    signalRConnection["hubName"].Call("GetValue", OnGetValueDone, OnGetValueFailed, OnGetValueProgress);
}
void OnGetValueDone(Hub hub, ClientMessage originalMessage, ResultMessage result)
{
    Debug.Log("GetValue executed on the server. Return value of the function:" + result.ReturnValue.ToString());
}
void OnGetValueFailed(Hub hub, ClientMessage originalMessage, FailureMessage error)
{
    Debug.Log("GetValue failed. Error message from the server: " + error.ErrorMessage);
}
void OnGetValueProgress(Hub hub, ClientMessage originalMessage, ProgressMessage progress)
{
    Debug.Log(string.Format("GetValue progressed: {0}%", progress.Progress));
}

Using the Hub class as a base class to inherit from

//使用Hub类作为从中继承的基类
//Hub类可以用作封装集线器功能的基类
class SampleHub : Hub
{
    // Default constructor. Every hubs have to have a valid name.  
    public SampleHub() : base("SampleHub")
    {
        // Register a server-callable function  
        base.On("ClientFunction", ClientFunctionImplementation);
    }

    // Private function to implement server-callable function  
    private void ClientFunctionImplementation(Hub hub, MethodCallMessage msg)
    {
        // TODO: implement  
    }

    // Wrapper function to call a server-side function.  
    public void ServerFunction(string argument)
    {
        base.Call("ServerFunction", argument);
    }
}
//这个SampleHub可以被实例化并传递给Connection的构造函数
void SampleHubImplement()
{
    Uri uri = new Uri("http://besthttpsignalr.azurewebsites.net/raw-connection/");
    SampleHub sampleHub = new SampleHub();
    Connection signalRConnection = new Connection(uri, sampleHub);
}

Authentication

Connection类具有AuthenticationProvider属性,可以将其设置为实现IAuthenticationProvider接口的对象

实现者必须实现以下属性和函数:
bool IsPreAuthRequired:如果必须在Connection类向服务器发出任何请求之前运行身份验证,则返回true。
示例:cookie身份验证器必须返回false,因为它必须发送用户凭据并接收必须随请求一起发送的cookie
StartAuthentication:仅当IsPreAuthRequired为true时才需要的函数。 否则它不会被调用
PrepareRequest:用请求和请求类型枚举调用的函数。 此功能可用于在请求发送到服务器之前准备请求
OnAuthenticationSucceded:当IsPreAuthRequired为true且认证过程成功时必须调用的事件
OnAuthenticationFailed:当IsPreAuthRequired为true且认证过程失败时必须调用的事件

//一个非常简单的基于Header的验证器看起来像这样:
//using BestHTTP.SignalR.Authentication;
class HeaderAuthenticator : IAuthenticationProvider
{
    public string User { get; private set; }
    public string Roles { get; private set; }

    // No pre-auth step required for this type of authentication    
    public bool IsPreAuthRequired { get { return false; } }

    // Not used event as IsPreAuthRequired is false    
    public event OnAuthenticationSuccededDelegate OnAuthenticationSucceded;

    // Not used event as IsPreAuthRequired is false    
    public event OnAuthenticationFailedDelegate OnAuthenticationFailed;

    // Constructor to initialise the authenticator with username and roles.    
    public HeaderAuthenticator(string user, string roles)
    {
        this.User = user;
        this.Roles = roles;
    }

    // Not used as IsPreAuthRequired is false    
    public void StartAuthentication() { }

    // Prepares the request by adding two headers to it   
    public void PrepareRequest(BestHTTP.HTTPRequest request, RequestTypes type)
    {
        request.SetHeader("username", this.User);
        request.SetHeader("roles", this.Roles);
    }
}

Writing custom Json encoders

编写自定义Json编码器
就像Socket.IO的Manager类一样,SignalR的Connection类具有JsonEncoder属性,并且也可以设置静态Connection.DefaultEncoder
JsonEncoder必须从BestHTTP.SignalR.JsonEncoders名称空间实现IJsonEncoder接口
此软件包包含一个样本LitJsonEncoder,也被一些例子使用

Server-Sent Events (EventSource)

Server-Sent Events是一种基于字符串的单向协议
数据来自服务器,并且没有选择向服务器发送任何内容。 它使用最新的草案实施
虽然协议的名称是Server-Sent Events,但该类本身被命名为EventSource。
当发生错误时,插件会在发送LastEventId后尝试重新连接,让服务器发送我们应该收到的任何缓冲消息

The EventSource class

//using BestHTTP.ServerSentEvents; 
void EventSourceClass()
{
    EventSource eventSource = new EventSource(new Uri("http://server.com"));

    //Properties 
    //这些是EventSource类公开公开的属性:
    //Uri:这是协议尝试连接的端点。 它通过构造函数设置。 
    //State:EventSource对象的当前状态。 
    //ReconnectionTime:尝试执行重新连接尝试需要等待多少时间。 它的默认值是2秒。
    //LastEventId:最近收到的事件的ID。 如果没有接收到事件ID,它将为空。
    //InternalRequest:将在Open函数中发出的内部HTTPRequest对象。

    //Events 
    //OnOpen:它在协议成功升级时调用
    eventSource.OnOpen += (source) => Debug.Log("EventSource Opened!"); 
    //OnMessage:它在客户端收到来自服务器的新消息时调用
    //该函数将接收一个Message对象,该对象包含Data属性中消息的有效内容
    //每次客户端收到消息时都会调用此事件,即使消息具有有效的事件名称,并且我们为此事件分配了事件处理程序!
    eventSource.OnError +=(source,error)=> Debug.Log("Error: " + error);
    //OnRetry:在插件尝试重新连接到服务器之前调用此函数。 如果函数返回false,则不会进行尝试,并关闭EventSource。
    eventSource.OnRetry += (source)=> false;
    //OnClosed:EventSource关闭时会调用此事件
    eventSource.OnClosed += (source) => Debug.Log("EventSource Closed!");
    //OnStateChanged:当State属性变化时调用
    eventSource.OnStateChanged += (source,oldState,newState)=> Debug.Log(string.Format("State Changed {0} => {1}", oldState, newState));

    //Functions 
    //这些是EventSource对象的公有方法
    // Open: 调用此函数后,插件将开始连接到服务器并升级到ServerSent Events协议
    eventSource.Open();
    // On: 使用这个功能,客户端可以订阅事件
    eventSource.On("userLogon", (source, msg) => { Debug.Log(msg.Data); });
    // Off: 它可以用来取消订阅活动
    eventSource.Close();
}

The Message class

Message类是一个逻辑单元,它包含服务器可以发送的所有信息。
属性
Id:发送事件的ID。 如果没有ID发送,可以为空。 它由插件使用。
Event:事件的名称。 如果没有发送事件名称,则可以为null。
Data:消息的实际有效负载。
Retry:服务器发送插件在尝试重新连接之前等待的时间。 它由插件使用

Logging

为了能够转储一些重要的 - 有时甚至是不太重要的 - 插件的功能,v1.7.0中引入了一个记录器接口和实现
默认的记录器可以通过HTTPManager.Logger属性进行访问
默认的日志级别是“调试版本的警告”和“其他版本的错误”
默认的记录器实现使用Unity的Debug.Log / LogWarning / LogError函数
可以通过从BestHTTP.Logger命名空间实现ILogger接口来编写新的记录器。

猜你喜欢

转载自blog.csdn.net/zcaixzy5211314/article/details/80228391