在system.net.socket中接收数据的实际方式

时间:2015-04-13 09:47:43

标签: c# sockets

我使用多线程异步套接字从XDomainRequest接收数据。到目前为止,我没有接收数据的问题,但我不喜欢我目前的做法。所以我想知道是否有更好的主意。

这是我的StateObject:

public class StateObject
{
    public Socket workSocket = null;
    public const int BufferSize = 256;
    public byte[] buffer = new byte[BufferSize];
    public StringBuilder sb = new StringBuilder();

    // stores total byte length which comes from XDomainRequest
    public int totalReceivedBuffer = 0;

    // stores byte lenght comes when each call of ReceiveCallBack
    public int receivedBuffer = 0;
}

在AcceptCallBack中,我创建了StateObject:

StateObject state = new StateObject();
state.workSocket = handler;

然后我必须做一个奇怪的事情来学习总接收字节:

System.Threading.Thread.Sleep(200);                 
state.totalReceivedBuffer = handler.Available;

如果我不睡觉,我得到的值小于实际值。在ReceiveCallBack方法中,我收到了一小部分数据的字节长度:

int numBytesReceived = handler.EndReceive(result);

我得到来自AcceptCallBack的StateObject并将接收到的字节添加到它:

state = (StateObject)result.AsyncState;
handler = state.workSocket;

state.receivedBuffer += numBytesReceived;

然后我控制它是否等于总字节数:

if(state.receivedBuffer == state.totalReceivedBuffer)
{
    // do the job
}
else
{
    // Call ReceiveCallBack again
}

有更好的方法吗?

修改

我在AcceptCallBack结束时调用ReceiveCallBack:

handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);

我的ReceiveCallBack功能在这里。我切了一些:

public static void ReceiveCallback(IAsyncResult result)
    {
        StateObject state = null;
        Socket handler = null;

        try
        {
            state = (StateObject)result.AsyncState;
            handler = state.workSocket;

            string clientIP = ((IPEndPoint)handler.RemoteEndPoint).Address.ToString();

            //  See how many bytes received
            int numBytesReceived = handler.EndReceive(result);

            if (!handler.Connected)
            {
                handler.Close();
                return;
            }


            if (numBytesReceived > 0)
            {
                state.receivedBuffer += numBytesReceived;

                state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, numBytesReceived));

                // Read all data line by line
                string[] lines = state.sb.ToString().Split('\n');

                if (state.receivedBuffer == state.totalReceivedBuffer)
                {
                    // All data came
                    // do the job according to lines array


                }
                else
                {
                    // continue receiving
                    handler.BeginReceive(state.buffer, 0, state.buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
                }
            }
        }
        catch (ObjectDisposedException ex)
        {
            // Don't care
        }
        catch (SocketException ex)
        {
            #region SocketException

            if (ex.ErrorCode == 10054)
            {
                // HATA: "An existing connection was forcibly closed by the remote host"
                Globals.ErrorLogYaz(_log, Globals.GetCurrentMethod(), "Karşı taraf işlem tamamlanmadan bağlantıyı kapattı!", ex.StackTrace);

                handler.Close();
            }

            #endregion
        }
        catch (Exception ex)
        {
            Globals.ErrorLogYaz(_log, Globals.GetCurrentMethod(), ex.Message, ex.StackTrace);

            handler.Close();
        }
    }

1 个答案:

答案 0 :(得分:0)

从连接中读取数据的方法是实际调用Receive并检查您获得的字节数。没有办法预测会有多少人来。 Available现在可用的数据量。接收方怎么可能知道发送者将来会发送多少钱?它无法知道。

在循环中调用Receive,直到它返回0(连接关闭)或直到你通过其他方式知道所有字节都被接收为止。

由于你似乎是一个带套接字的初学者,并且似乎没有理由使用异步,你可能应该使用同步IO。它简单得多。