C# 异步套接字服务器接收问题 [英] C# Async Sockets Server Receive Problems

查看:27
本文介绍了C# 异步套接字服务器接收问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经在这里实现了关于这篇文章的服务器应用程序:http://www.codeguru.com/csharp/csharp/cs_network/sockets/article.php/c8781#Client1

I have implemented my Server application regarding this post here: http://www.codeguru.com/csharp/csharp/cs_network/sockets/article.php/c8781#Client1

总结:我正在使用异步套接字 ala BeginAccept(..)、BeginReceive(..).我的服务器能够处理多个客户端并且一切正常,直到客户端执行两个或多个同步发送操作而无需等待一段时间.客户端没有收到任何错误,因此不会收到通知,即服务器没有收到第二条消息!如果客户端等待大约.第一次发送操作后 100 毫秒,一切正常.我认为当我使用 TCP 时,我可以确保服务器收到消息.(除非抛出异常)!你能给我一个解决方案来解决这个问题.

Sum up: I am using async Sockets ala BeginAccept(..), BeginReceive(..). My Server is capable of handling mutliple clients and everything works fine until a client performas two or more synchronous send operation without waiting some time. The client does not get any error and so is not notified, that the server does not get the second message! If the client waits approx. 100ms after the first send operation, everything works fine. I thought that when i use TCP i can ensure that the server receives the message. (Except there is an exception thrown)! Could you provide me a solution to fix this.

这里是 WaitForData(..) &我在服务器中实现的 OnDataReceive(..) 方法

Here are the WaitForData(..) & OnDataReceive(..) Methods that i implemented in the server

public void WaitForData(MyClient client)
{
    try
    {
        if (pfnCallBack == null)
        {
            pfnCallBack = new AsyncCallback(OnDataReceived);
        }

        iarResult = client.Socket.BeginReceive(client.DataBuffer,
                                                0, client.DataBuffer.Length,
                                                SocketFlags.None,
                                                pfnCallBack,
                                                client);
    }
    catch (SocketException se)
    {
        MessageBox.Show("SocketException@WaitForData" + se.Message);
    }
}
public void OnDataReceived(IAsyncResult asyn)
{
    try
    {
        MyClient user= (MyClient)asyn.AsyncState;
        int iRx = user.Socket.EndReceive(asyn);

        byte[] receivedData = user.DataBuffer;

        MemoryStream memStream = new MemoryStream();
        BinaryFormatter binForm = new BinaryFormatter();
        memStream.Write(receivedData, 0, receivedData.Length);
        memStream.Seek(0, SeekOrigin.Begin);
        MyMessage msg = (MyMessage)binForm.Deserialize(memStream);

        switch (msg.Command)
        {
            case (MyMessage.MyCommand.ConnId):
                this.connId = (int) msg.MyObject;
                tsslConnStatus.Text += " | ID: " + connId.ToString();
            break;

            case (MyMessage.MyCommand.Text):
                MessageBox.Show(msg.MyObject.ToString());
                break;
        }
        WaitForData(server);
    }
    catch (ObjectDisposedException ode)
    {
        MessageBox.Show("ObjectDisposedException@OnReceiveData" + ode.Message);
    }
    catch (SocketException se)
    {
        MessageBox.Show("SocketException@OnReceiveData" + se.Message);
    }
}

客户端调用同步发送方法两次或更多次!服务器实例我的客户端

The CLIENT calls a synchronous SEND METHOD TWICE or MORE! server INSTANCEOF MyClient

if (server.Socket.Connected)
{
    BinaryFormatter bf = new BinaryFormatter();
    MemoryStream ms = new MemoryStream();
    bf.Serialize(ms, message);
    MyMessage = new MyMessage(something);
    server.Socket.Send(ms.ToArray());
}

所以,我认为这些代码片段必须足以让您了解我尝试使用的想法!如果您需要更多详细信息或代码片段,请告诉我我会发布它!

so, i think this code snippets must be enough for you to get the idea i was trying to use! If you need further details or code snippets, just tell me i will post it!

谢谢!

推荐答案

TCP 是基于流而不是基于消息的.一个 Read 可以包含以下任一选项:

TCP is stream based and not message based. One Read can contain any of the following alternatives:

  • 信息的一小部分
  • 半信息
  • 只有一条消息
  • 一个半消息
  • 两条消息

因此您需要使用某种方法来查看是否有完整的消息到达.最常用的方法是:

Thus you need to use some kind of method to see if a complete message have arrived. The most common methods are:

  • 添加表示消息结束的页脚(例如空行)
  • 添加包含消息长度的固定长度标头

只有长度作为标题的简单示例.

Simple example having just length as header.

服务器端:

var buffer = binaryFormmater.Serialize(myobj);
var length = buffer.Length;
networkStream.Send(length);
networkStream.Send(buffer, 0, buffer.Length);

客户端:

var header = new buffer[4];
// TODO: You need to make sure that 4 bytes have been read.
networkStream.Read(header, 0, 4);
var length = BitConverter.ToInt32(buffer);

var readbuffer= new byte[65535];
var bytesLeft = length;
var messageStream = new MemoryStream();
while (bytesLeft > 0)
{
     var read = networkStream.Read(readbuffer, 0, bytesLeft);
     messageStream.Write(readbuffer, 0, read);
     bytesLeft -= read,
}

messageStream.Seek(0, SeekOrigin.Begin);
MyMessage msg = (MyMessage)binForm.Deserialize(messageStream);

这篇关于C# 异步套接字服务器接收问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆