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

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

问题描述

我已经实现在这里就这个帖子我的服​​务器应用程序:的http://www.$c$cguru.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(..)。
我的服务器能够处理复式客户,直到客户performas两个或多个同步发送操作,而无需等待一段时间,一切工作正常。客户端没有得到任何错误,所以不通知,该服务器没有得到第二条消息!如果客户端等待约。 100ms的第一个发送操作之后,一切工作正常。
我想,当我使用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);
    }
}

客户端调用同步发送方法两次或两次以上!服务器INSTANCEOF MyClient

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());
}

所以,我认为这code段必须足够让你的想法我试图用!
如果您需要进一步细节或code片段,只是告诉我,我将它张贴!

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是基于基于流,而不是消息。其中可以包含以下任何替代方案:

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


  • 消息的蝇头纤细部分

  • 半消息

  • Excactly一个消息

  • 一个半消息

  • 两个消息

因此​​,你需要使用某种方法,看有没有完整的消息已到达。最常见的方法是:

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天全站免登陆