为 BeginReceive 提供的字节

发布于 2024-09-08 12:42:20 字数 3752 浏览 6 评论 0原文

我的程序所做的是,首先连接接受,服务器发送数据 客户端接收然后再次发送(数据大小不变) 服务器接收到它然后再次发回....这个循环继续...

当服务器第二次接收数据时endreceive()返回的int;是 0

虽然我已经找到了解决方案,但我不知道为什么这实际上解决了

我在某处读到的问题,有一个叫做“脏”缓冲区的东西:

所以我所做的是。

//added line
data = new byte[DataSize];

//now index works fine :s
int index = socket.endreceive(result);

以前我重复使用byte[] data 进行发送和接收而不更改其内容,数据发送全为零

并且它有效:)

msdn 没有帮助我,或者我错过了什么? MSDN 链接

这是我提供的 SendCallback 和 Receive Callback 代码的汇总代码

    private void OnSendCallBack(IAsyncResult result)
    {
        int id_client = (int)result.AsyncState;
        try
        {

            int index = clientInfo[id_client].client.EndSend(result);

            clientInfo[id_client].offsetSend += index;
            if (index == 0)
            {
                Console.WriteLine("Index == 0");
                return;
            }
            else if (clientInfo[id_client].offsetSend < DataSize)
            {
                clientInfo[id_client].dataToSend = DataSize - clientInfo[id_client].offsetSend;
                clientInfo[id_client].client.BeginSend(data, clientInfo[id_client].offsetSend, clientInfo[id_client].dataToSend, SocketFlags.None, RecieveCallBack, id_client);
            }
            else 
            {
                clientInfo[id_client].offsetSend = 0;
                clientInfo[id_client].dataToSend = DataSize;
                //*************************************
                data = new byte[DataSize]; // THIS IS THE PROBLEM HERE
                //*************************************
                clientInfo[id_client].client.BeginReceive(data, 0, data.Length, SocketFlags.None, RecieveCallBack, id_client);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("Send: " + ex.Message);
        }
    }

private void RecieveCallBack(IAsyncResult result)
    {
        int id_client = (int)result.AsyncState;

        try
        {

            int index = clientInfo[id_client].client.EndReceive(result);

            //byte[] buffer = new byte[DataSize];
            //int received = clientInfo[id_client].client.Receive(buffer);

            clientInfo[id_client].offsetRec += index;
            if (index == 0)
            {
                index = clientInfo[id_client].client.EndReceive(result);
                Console.WriteLine("Index == 0");
                return;
            }
            else if (clientInfo[id_client].offsetRec < DataSize && clientInfo[id_client].offsetRec != 0)
            {
                clientInfo[id_client].dataToReceive = DataSize - clientInfo[id_client].offsetRec;
                clientInfo[id_client].client.BeginReceive(data, clientInfo[id_client].offsetRec, clientInfo[id_client].dataToReceive, SocketFlags.None, RecieveCallBack, id_client);
            }
            else
            {
                clientInfo[id_client].offsetRec = 0;
                clientInfo[id_client].dataToReceive = DataSize;

                if (clientInfo[id_client].RunNumber < RounCount)
                {
                    clientInfo[id_client].RoundTripStat.EndSample();
                    clientInfo[id_client].RoundTripStat.BeginSample(); 
                    clientInfo[id_client].client.BeginSend(data, 0, data.Length, SocketFlags.None, OnSendCallBack, id_client); 
                }

                Close(id_client);
            }

        }
        catch (Exception ex)
        {
            Console.WriteLine("Server: " + ex.Message);
        }
    }

,您可以看到一个异步命令一次等待一个

what my program does is, At first connection accept, server sends data
the client receive then sends again (Datasize does not change)
Server receives it then sends back again .... this loop continues ...

when the second time the server receives data the int returned by endreceive(); is 0

although i have found the solution but i dont know why does this actually solve the problem

i read somehewhere that there is something called 'dirty' buffer :s

so what i did was.

//added line
data = new byte[DataSize];

//now index works fine :s
int index = socket.endreceive(result);

previously i was reusing byte[] data for send and receive without changing its contents, data send is all zeros

and it worked :)

msdn doesnt help me there or have i missed somwthing ?
MSDN Link

This is the summarized code

    private void OnSendCallBack(IAsyncResult result)
    {
        int id_client = (int)result.AsyncState;
        try
        {

            int index = clientInfo[id_client].client.EndSend(result);

            clientInfo[id_client].offsetSend += index;
            if (index == 0)
            {
                Console.WriteLine("Index == 0");
                return;
            }
            else if (clientInfo[id_client].offsetSend < DataSize)
            {
                clientInfo[id_client].dataToSend = DataSize - clientInfo[id_client].offsetSend;
                clientInfo[id_client].client.BeginSend(data, clientInfo[id_client].offsetSend, clientInfo[id_client].dataToSend, SocketFlags.None, RecieveCallBack, id_client);
            }
            else 
            {
                clientInfo[id_client].offsetSend = 0;
                clientInfo[id_client].dataToSend = DataSize;
                //*************************************
                data = new byte[DataSize]; // THIS IS THE PROBLEM HERE
                //*************************************
                clientInfo[id_client].client.BeginReceive(data, 0, data.Length, SocketFlags.None, RecieveCallBack, id_client);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("Send: " + ex.Message);
        }
    }

private void RecieveCallBack(IAsyncResult result)
    {
        int id_client = (int)result.AsyncState;

        try
        {

            int index = clientInfo[id_client].client.EndReceive(result);

            //byte[] buffer = new byte[DataSize];
            //int received = clientInfo[id_client].client.Receive(buffer);

            clientInfo[id_client].offsetRec += index;
            if (index == 0)
            {
                index = clientInfo[id_client].client.EndReceive(result);
                Console.WriteLine("Index == 0");
                return;
            }
            else if (clientInfo[id_client].offsetRec < DataSize && clientInfo[id_client].offsetRec != 0)
            {
                clientInfo[id_client].dataToReceive = DataSize - clientInfo[id_client].offsetRec;
                clientInfo[id_client].client.BeginReceive(data, clientInfo[id_client].offsetRec, clientInfo[id_client].dataToReceive, SocketFlags.None, RecieveCallBack, id_client);
            }
            else
            {
                clientInfo[id_client].offsetRec = 0;
                clientInfo[id_client].dataToReceive = DataSize;

                if (clientInfo[id_client].RunNumber < RounCount)
                {
                    clientInfo[id_client].RoundTripStat.EndSample();
                    clientInfo[id_client].RoundTripStat.BeginSample(); 
                    clientInfo[id_client].client.BeginSend(data, 0, data.Length, SocketFlags.None, OnSendCallBack, id_client); 
                }

                Close(id_client);
            }

        }
        catch (Exception ex)
        {
            Console.WriteLine("Server: " + ex.Message);
        }
    }

I have provided code of SendCallback and Receive Callback, as you can see one asynch command is waiting one at a time

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

三生殊途 2024-09-15 12:42:20

如果没有更多数据要接收,并且套接字已关闭(即没有更多数据要接收),EndReceive() 返回 0。

从您提到的文档中:

如果远程主机使用 Shutdown 方法关闭 Socket 连接,并且已接收到所有可用数据,则 EndReceive 方法将立即完成并返回零字节。

通常,您不应该重复使用相同的缓冲区来发送和接收 - 您最终将发送收到的任何数据,并且如果您有重叠的发送和接收异步调用,则可能最终会处于非常奇怪的状态。

只有一次只执行一项操作,并且确保在写入时,您拥有明确设置的确切数据时,“共享”缓冲区才是安全的。

EndReceive() returns 0 if there was no more data to receive, and the socket has been closed (i.e. there will be no more data to receive).

From the docs you referred to:

If the remote host shuts down the Socket connection with the Shutdown method, and all available data has been received, the EndReceive method will complete immediately and return zero bytes.

You shouldn't generally reuse the same buffer for both sending and receiving - you'll end up sending whatever data you received, and if you have overlapping send and receive asynchronous calls it'll end up in a very strange state, potentially.

It's only safe to "share" the buffer if you only ever perform one operation at a time, and you make sure that when you write, you have exactly the data you want, explicitly set there.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文