1

我正在开发一个服务器(使用 c#)和一个客户端(使用 flash,actionscript 3.0)应用程序。服务器连续向客户端发送数据(数据约为 90 字节),客户端根据收到的数据运行(数据为 json 格式)

有一段时间,一切都按预期工作,但经过一段时间后,客户端开始接收延迟消息。他们继续等待一段时间,然后他们根据最后一条消息(一些消息丢失)行事。经过一段时间后,客户端开始等待并同时处理所有消息。我不知道是什么原因造成的。我的网络状况稳定。

这是我的 C# 代码的一部分,发送消息:

public void Send(byte[] buffer)
    {
        if (ClientSocket != null && ClientSocket.Connected)
        {
            ClientSocket.BeginSend(buffer, 0, buffer.Length, 0, WriteCallback, ClientSocket);
        }
    }

    private void WriteCallback(IAsyncResult result)
    {
        //
    }

和我的客户的某些部分,接收消息(动作脚本)

socket.addEventListener(ProgressEvent.SOCKET_DATA, onResponse);
function onResponse(e:ProgressEvent):void {
trace(socket.bytesAvailable);
if(socket.bytesAvailable > 0) {
    try
    {
        var serverResponse:String = socket.readUTFBytes(socket.bytesAvailable);

……

我希望我能解释我的问题。我应该如何优化我的代码?什么可能导致滞后。谢谢。

4

1 回答 1

2

您确实需要详细说明如何设置套接字(是 TCP 还是 UDP?)

假设它是一个 TCP 套接字,那么您的客户端似乎依赖于每个接收调用,它们返回的字节数与服务器Send()调用发送的字节数相同。然而,情况并非如此,如果在客户端上仅收到部分消息,或者一次收到多条消息,则很可能是您的问题的原因。

例如,服务器可能会在一次调用中发送一条 90 字节的消息,但您的客户端可能会以一个 90 字节的接收、或两个 45 字节的块、甚至 90 x 1 字节的块或介于两者之间的任何方式接收它。服务器发送的多条消息在客户端接收时也可能部分组合。例如,可以在一个 180 字节的块中接收两个 90 字节的消息,或者一个 150 字节和一个 30 字节的块等。

因此,您需要为您的消息提供某种框架,以便当客户端接收到数据流时,它可以可靠地重建为单独的消息。

最基本的成帧机制是在每条发送的消息前加上一个固定长度的字段来指示消息的大小。如果您可以保证您的消息永远不会超过 255 个字节,那么您可能能够摆脱单个字节,这将简化接收代码。

在客户端,您首先需要接收长度前缀,然后从套接字读取那么多字节来构造消息数据。如果您收到的字节数少于所需的字节数,您的接收代码必须等待更多数据(在最终收到时将其附加到部分接收的消息中),直到它有完整的消息。

一旦收到完整的消息,就可以按您当前的方式处理它。

不幸的是,我不了解 ActionScript,因此无法为您提供客户端代码的示例,但您可以使用 C# 编写服务器和客户端框架:

服务器端:

public void SendMessage(string message)
{
    var data = Encoding.UTF8.GetBytes(message);
    if (data.Length > byte.MaxValue) throw new Exception("Data exceeds maximum size");
    var bufferList = new[]
    {
        new ArraySegment<byte>(new[] {(byte) data.Length}),
        new ArraySegment<byte>(data)
    };
    ClientSocket.Send(bufferList);
}

客户端:

public string ReadMessage()
{
    var header = new byte[1];
    // Read the header indicating the data length
    var bytesRead = ServerSocket.Receive(header);
    if (bytesRead > 0)
    {
        var dataLength = header[0];
        // If the message size is zero, return an empty string
        if (dataLength == 0) return string.Empty;
        var buffer = new byte[dataLength];
        var position = 0;
        while ((bytesRead = ServerSocket.Receive(buffer, position, buffer.Length - position, SocketFlags.None)) > 0)
        {
            // Advance the position by the number of bytes read
            position += bytesRead;
            // If there's still more data to read before we have a full message, call Receive again
            if (position < buffer.Length) continue;
            // We have a complete message - return it.
            return Encoding.UTF8.GetString(buffer);
        }
    }
    // If Receive returns 0, the socket has been closed, so return null to indicate this.
    return null;
}
于 2012-06-13T02:24:09.567 回答