接收正确数量的数据 TCP [英] Receive correct amount of data TCP

查看:21
本文介绍了接收正确数量的数据 TCP的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 C# 启动 TCP 异步服务器,并且我正在努力寻找从服务器接收正确数量的数据的正确方法.我的问题是:由于 TCP 是 STREAM 协议的性质,在收到的每条消息的末尾没有分隔符,所以我唯一能做的就是在消息的开头添加即将到来的消息大小并因此做出反应;问题是,我如何接收并确保我没有阅读流中的下一个"消息?

I'm bringing up a TCP async server using C# and I'm struggling on the right way to receive the correct amount of data from the server. My question is this one: due to the nature of TCP being a STREAM protocol, there is no delimiter at the end of each message received so the only thing I can do is add at the beginning of the message the upcoming message size and react consequently; the thing is, how can I recv and be sure that I'm not reading the "next" message in the stream?

我的伪代码如下:

// client accepted, begin receiving
client.BeginReceive(state.buffer, 0, StateObject.bufferSize, 0, new AsyncCallback(_cbck_Read), state);

private void _cbck_Read(IAsyncResult ar)
{

    StateObject state  = (StateObject)ar.AsyncState;
    Socket client      = state.clientSocket; 

    int bytesRead = client.EndReceive(ar);

        // if data have been received
        if (bytesRead > 0)
        {
            state.bytesReceived += bytesRead;

            // no message header received so far go on reading
            if (state.bytesReceived < Marshal.SizeOf(header))
            {
                client.BeginReceive(state.buffer, 0, StateObject.bufferSize, 0, new AsyncCallback(_cbck_Read), state);
            }

 // ... go ahead reading

如果第一个 recv 没有收到完整的消息,下一个 recv 是否会远远超出第一个的边界,并可能在我真正想要阅读的消息中添加一些不需要的字节?

If the first recv does not get the whole message, could the next recv go far beyond the boundaries of the first and possibly add some unwanted bytes to the message I'm actually wanting to read?

推荐答案

这里是如何使用 async/await" 和一些辅助扩展方法来完成的.

Here is how it can be done using "async/await" with some helper extension methods.

Socket s = new Socket(SocketType.Stream, ProtocolType.Tcp);
await s.ConnectTaskAsync("stackoverflow.com", 80);

await s.SendTaskAsync(Encoding.UTF8.GetBytes("GET /\r\n\r\n"));


var buf1 = await s.ReceiveExactTaskAsync(100); //read exactly 100 bytes
Console.Write(Encoding.UTF8.GetString(buf1));

var buf2 = await s.ReceiveExactTaskAsync(100); //read exactly 100 bytes
Console.Write(Encoding.UTF8.GetString(buf2));

<小时>

public static class SocketExtensions
{
    public static Task<int> ReceiveTaskAsync(this Socket socket, byte[] buffer, int offset, int count)
    {
        return Task.Factory.FromAsync<int>(
                         socket.BeginReceive(buffer, offset, count, SocketFlags.None, null, socket),
                         socket.EndReceive);
    }

    public static async Task<byte[]> ReceiveExactTaskAsync(this Socket socket, int len)
    {
        byte[] buf = new byte[len];
        int totalRead = 0;
        do{
            int read = await ReceiveTaskAsync(socket, buf, totalRead, buf.Length - totalRead);
            if (read <= 0) throw new SocketException();
            totalRead += read;
        }while (totalRead != buf.Length);
        return buf;
    }

    public static Task ConnectTaskAsync(this Socket socket, string host, int port)
    {
        return Task.Factory.FromAsync(
                         socket.BeginConnect(host, port, null, null),
                         socket.EndConnect);
    }

    public static Task SendTaskAsync(this Socket socket, byte[] buffer)
    {
        return Task.Factory.FromAsync<int>(
                         socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, null, socket),
                         socket.EndSend);
    }
}

这篇关于接收正确数量的数据 TCP的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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