Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 套接字OnData事件_C#_Sockets_Events - Fatal编程技术网

C# 套接字OnData事件

C# 套接字OnData事件,c#,sockets,events,C#,Sockets,Events,我现在有点困难。我有一些代码可以在数据可用时从套接字读取数据,但目前它在一个单独线程上的while循环中,当函数返回时,由于没有可用数据,它会占用50%的CPU。我真正想要的是一个用于套接字的阻塞函数,它会阻塞直到数据可用为止,或者至少是一个可以监听的OnData事件。我最初从AS3(Flash)转换了这段代码,但是他们的sockets类有我需要的OnData事件。。。只是用错了语言 我目前在处理客户端连接的代码中包含以下代码: ServerThread = new Thread(() =>

我现在有点困难。我有一些代码可以在数据可用时从套接字读取数据,但目前它在一个单独线程上的while循环中,当函数返回时,由于没有可用数据,它会占用50%的CPU。我真正想要的是一个用于套接字的阻塞函数,它会阻塞直到数据可用为止,或者至少是一个可以监听的OnData事件。我最初从AS3(Flash)转换了这段代码,但是他们的sockets类有我需要的OnData事件。。。只是用错了语言

我目前在处理客户端连接的代码中包含以下代码:

ServerThread = new Thread(() =>
{
    while (server.Connected && ServerContinue)
    {
        ReceiveFromServer(server, client);
    }

    Disconnect(server, client, false);
});

ServerThread.Start();
这是ReceiveFromServer中的代码:

bool isReady = false;
int messageLength = 0;
int dataAvailable = 0;
UInt16 packetSize = 0;
byte[] temp = new byte[2];
do
{
    dataAvailable = server.Available;
    if (isReady)
    {
        if (dataAvailable >= messageLength)
        {
            byte[] temp1 = new byte[2000];
            int bytesRead = server.Receive(temp1, 0, messageLength, SocketFlags.None);

            byte[] data = new byte[bytesRead + 2];
            Buffer.BlockCopy(temp1, 0, data, 2, messageLength);

            Helpers.ByteArray tempo = data;
            tempo.writeByte(temp[1]);
            tempo.writeByte(temp[0]);
            if (!VersionCheckPass)
            {
                Send(tempo, client);
                return;
            }

            ServerPacketHandler(tempo, client);
            messageLength = 0;
            isReady = false;
            temp = new byte[2];
        }
    }
    else if(dataAvailable > 2)
    {
        server.Receive(temp, 0, 2, SocketFlags.None);
        temp = temp.Reverse().ToArray();
        packetSize = BitConverter.ToUInt16(temp, 0);
        if (packetSize > 0)
        {
            messageLength = packetSize;
            isReady = true;
        }
    }
}
while (dataAvailable > 2 && dataAvailable >= messageLength && ServerContinue);
但这里的问题是,当dataAvailable为0时,函数只返回,然后在线程中再次调用ReceiveFromServer。这意味着,只需调用ReceiveFromServer,然后再次返回,就可以使用大量CPU


我目前在ServerThread中有
线程。在从服务器接收后睡眠(10)
,但这是低效的。所以我的问题是,是否有一种方法可以阻止数据,直到数据可用,或者是否有一个我可以处理的事件?或者其他人对如何做与我目前正在做的相同的事情有什么建议,但它不会在没有可用数据的情况下无休止地循环。

不需要太多的重写。您的代码看起来只是接收消息,然后传递到另一个例程来处理它

我对这个帖子的回复几乎涵盖了您想要做的事情:

我的socketReadCallBack函数是:

    private void OnDataReceived(IAsyncResult asyn)
    {
        ReceiveState rState = (ReceiveState)asyn.AsyncState;
        Socket client = rState.Client;
        SocketError socketError = SocketError.TypeNotFound;

        if (!client.Connected)
        {
            // Not Connected anymore ?
            return;
        }

        _LastComms = DateTime.Now;
        _LastIn = _LastComms;

        int dataOffset = 0; 
        int restOfData = 0;
        int dataRead = 0;
        Boolean StreamClosed = false;
        long rStateDataLength = 0;
        long LastrStateDataLength = 0;

        try
        {

            dataRead = client.EndReceive(asyn, out socketError);
        }
        catch (Exception excpt)
        {
            // Handle error - use your own code..

        }

        if (socketError != SocketError.Success)
        {
            // Has Connection been lost ?
            OnConnectionDropped(client);
            return;
        }

        if (dataRead <= 0)
        {
            // Has connection been lost ?
            OnConnectionDropped(client);
            return;
        }

        while (dataRead > 0)
        {
            //check to determine what income data contain: size prefix or message
            if (!rState.DataSizeReceived)
            {
                //there is already some data in the buffer
                if (rState.Data.Length > 0)
                {
                    restOfData = PrefixSize - (int)rState.Data.Length;
                    rState.Data.Write(rState.Buffer, dataOffset, restOfData);
                    dataRead -= restOfData;
                    dataOffset += restOfData;
                }
                else if (dataRead >= PrefixSize)
                {  //store whole data size prefix
                    rState.Data.Write(rState.Buffer, dataOffset, PrefixSize);
                    dataRead -= PrefixSize;
                    dataOffset += PrefixSize;
                }
                else
                {  // store only part of the size prefix
                    rState.Data.Write(rState.Buffer, dataOffset, dataRead);
                    dataOffset += dataRead;
                    dataRead = 0;
                }

                if (rState.Data.Length == PrefixSize)
                {  //we received data size prefix 
                    rState.DataSize = BitConverter.ToInt32(rState.Data.GetBuffer(), 0);
                    rState.DataSizeReceived = true;
                    //reset internal data stream             
                    rState.Data.Position = 0;
                    rState.Data.SetLength(0);
                }
                else
                {  //we received just part of the prefix information 
                    //issue another read
                    client.BeginReceive(rState.Buffer, 0, rState.Buffer.Length,
                       SocketFlags.None, new AsyncCallback(socketReadCallBack),
                          rState);
                    return;
                }
            }



            //at this point we know the size of the pending data

            // Object disposed exception may raise here
            try
            {
                rStateDataLength = rState.Data.Length;
                LastrStateDataLength = rStateDataLength;
            }
            catch (ObjectDisposedException Ode)
            {
                StreamClosed = true;
            }
            if (!StreamClosed)
            {

                if ((rStateDataLength + dataRead) >= rState.DataSize)
                {   //we have all the data for this message

                    restOfData = rState.DataSize - (int)rState.Data.Length;

                    rState.Data.Write(rState.Buffer, dataOffset, restOfData);
                    //Console.WriteLine("Data message received. Size: {0}",
                    //   rState.DataSize);

                    // Is this a heartbeat message ?
                    if (rState.Data.Length == 2)
                    {
                        // Yes
                        HeartBeatReceived();
                    }
                    else
                    {
                        //charArray = new char[uniEncoding.GetCharCount(
                        //byteArray, 0, count)];
                        //uniEncoding.GetDecoder().GetChars(
                        //    byteArray, 0, count, charArray, 0);
                        //Console.WriteLine(charArray);

                        //rState.Data.Position = 0;

                        DecodeMessageReceived(GetStringFromStream(rState.Data));
                    }

                    dataOffset += restOfData;
                    dataRead -= restOfData;

                    //message received - cleanup internal memory stream
                    rState.Data = new MemoryStream();
                    rState.Data.Position = 0;
                    rState.DataSizeReceived = false;
                    rState.DataSize = 0;

                    if (dataRead == 0)
                    {  
                        //no more data remaining to process - issue another receive
                        if (_IsConnected)
                        {
                            client.BeginReceive(rState.Buffer, 0, rState.Buffer.Length,
                               SocketFlags.None, new AsyncCallback(socketReadCallBack),
                                  rState);
                            return;
                        }
                    }
                    else
                        continue; //there's still some data to process in the buffers
                }
                else
                {  //there is still data pending, store what we've 
                    //received and issue another BeginReceive
                    if (_IsConnected)
                    {
                        rState.Data.Write(rState.Buffer, dataOffset, dataRead);

                        client.BeginReceive(rState.Buffer, 0, rState.Buffer.Length,
                           SocketFlags.None, new AsyncCallback(socketReadCallBack), rState);

                        dataRead = 0;
                    }
                }
            }
            else
            {
                // Stream closed, but have we read everything ?
                if (LastrStateDataLength + dataRead == rState.DataSize)
                {
                    // We're equal, get ready for more
                    //no more data remaining to process - issue another receive
                    if (_IsConnected)
                    {
                        client.BeginReceive(rState.Buffer, 0, rState.Buffer.Length,
                           SocketFlags.None, new AsyncCallback(socketReadCallBack),
                              rState);
                    }
                    return;
                }
                else
                {
                    // We should have more..
                    // Report Error
                }
            }

            // If we've been disconnected, provide a graceful exit
            if (!_IsConnected)
                dataRead = -1;

        }
     }
private void OnDataReceived(IAsyncResult asyn)
{
ReceiveState RSState=(ReceiveState)asyn.AsyncState;
socketclient=rState.client;
SocketError SocketError=SocketError.TypeNotFound;
如果(!client.Connected)
{
//不再连接了?
返回;
}
_LastComms=DateTime.Now;
_LastIn=\u LastComms;
int dataOffset=0;
int restOfData=0;
int dataRead=0;
布尔流闭合=假;
长rStateDataLength=0;
long LastrStateDataLength=0;
尝试
{
dataRead=client.EndReceive(asyn,out-socketError);
}
捕获(例外情况除外)
{
//处理错误-使用您自己的代码。。
}
if(socketError!=socketError.Success)
{
//连接断了吗?
OnConnectionDropped(客户端);
返回;
}
如果(数据读取0)
{
//检查以确定收入数据包含的内容:大小前缀或消息
如果(!rState.DataSizeReceived)
{
//缓冲区中已经有一些数据
如果(rState.Data.Length>0)
{
restOfData=PrefixSize-(int)rState.Data.Length;
rState.Data.Write(rState.Buffer、dataOffset、restOfData);
dataRead-=restOfData;
dataOffset+=restOfData;
}
else if(数据读取>=前缀大小)
{//存储整个数据大小前缀
rState.Data.Write(rState.Buffer、dataOffset、PrefixSize);
dataRead-=前缀大小;
dataOffset+=前缀大小;
}
其他的
{//仅存储部分大小前缀
rState.Data.Write(rState.Buffer、dataOffset、dataRead);
dataOffset+=数据读取;
dataRead=0;
}
if(rState.Data.Length==前缀大小)
{//我们收到了数据大小前缀
rState.DataSize=BitConverter.ToInt32(rState.Data.GetBuffer(),0);
rState.DataSizeReceived=true;
//重置内部数据流
rState.Data.Position=0;
rState.Data.SetLength(0);
}
其他的
{//我们只收到了部分前缀信息
//再读一读
client.BeginReceive(rState.Buffer,0,rState.Buffer.Length,
SocketFlags.None,新的异步回调(socketReadCallBack),
国家);
返回;
}
}
//此时,我们知道挂起数据的大小
//此处可能会引发对象处理异常
尝试
{
rStateDataLength=rState.Data.Length;
LastrStateDataLength=rStateDataLength;
}
捕获(ObjectDisposedException Ode)
{
StreamClosed=true;
}
如果(!StreamClosed)
{
如果((rStateDataLength+dataRead)>=rState.DataSize)
{//我们有此邮件的所有数据
restOfData=rState.DataSize-(int)rState.Data.Length;
rState.Data.Write(rState.Buffer、dataOffset、restOfData);
//Console.WriteLine(“接收到数据消息。大小:{0}”),
//rState.DataSize);
//这是心跳信号吗?
if(rState.Data.Length==2)
{
//对
心脏跳动();
}
其他的
{
//charArray=new char[uniEncoding.GetCharCount(
//byteArray,0,count)];
//uniEncoding.GetDecoder().GetChars(
//byteArray,0,count,charArray,0);
//控制台写入线(charArray);
//rState.Data.Position=0;
DecodeMessageReceived(GetStringFromStream)(r
ServerThread = new Thread(() =>
{
    byte[] zero = new byte[0];
    while (Server.Connected && ServerContinue)
    {
        server.Receive(zero, 0, SocketFlags.None);
        ReceiveFromServer(server, client);
    }

    Disconnect(server, client, false);
});