【问题标题】:Receiving Packet using Socket使用 Socket 接收数据包
【发布时间】:2013-05-20 14:22:31
【问题描述】:

我是 Socket 编程的新手,我只是想问一些问题。

我试图在客户端和服务器之间创建简单的接收方和发送方数据包(我使用的是同一台计算机),但我遇到了问题......

发送功能正常,但我不知道如何接收发送的数据包大小完全相同。

例如,我从客户端向服务器发送 5 个字节,我只想让服务器也只接收 5 个字节,不多也不少,我想用 Socket 来做,而且我已经包含了短(int16 2 字节)格式的数据包。这是我的发送数据包代码:

    public static void Send(Socket socket, byte[] buffer, int timeout)
    {
        int startTickCount = Environment.TickCount;
        int sent = 0;
        int offset = 0;
        int size = buffer.Length;

        // Add size of packet in the begin of data packet with short (int16) format
        List<byte> tmpdata = new List<byte>();
        tmpdata.AddRange(BitConverter.GetBytes((short)(buffer.Length + 2)));
        tmpdata.AddRange(buffer);
        buffer = tmpdata.ToArray();

        do
        {
            if (Environment.TickCount > startTickCount + timeout)
                throw new Exception("Sending packet was timeout.");
            try
            {
                sent += socket.Send(buffer, offset + sent, size - sent, SocketFlags.None);
            }
            catch (SocketException ex)
            {
                if (ex.SocketErrorCode == SocketError.WouldBlock ||
                    ex.SocketErrorCode == SocketError.IOPending ||
                    ex.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
                {
                    Thread.Sleep(30);
                }
                else
                    throw ex;
            }
        } while (sent < size);
    }

有人可以帮我吗?


感谢 Damien 的修复 我找到了解决方案,但我担心这会消耗内存,因为它循环每个字节,这里是代码:

    public static byte[] Receive(Socket socket)
    {
        System.Net.Sockets.NetworkStream ns = new NetworkStream(socket);
        int b = (byte)1;
        List<byte> databuf = new List<byte>();

        while ((b = ns.ReadByte()) != -1)
            databuf.Add((byte)b);

        return databuf.ToArray();
    }

有没有更好的解决方案没有 NetworkStream 或者更好的性能? 谢谢

【问题讨论】:

  • 你应该使用服务器 Socket 的 Bind()Accept() 方法,如果你释放你的尝试来修复它可能会很好。
  • 您在接收端的阅读应该只收到您发送给它的内容。显示您的接收代码并解释您看到的行为。

标签: c# sockets


【解决方案1】:

您没有显示您的接收代码,但可以轻松修复一个错误:

    // Add size of packet in the begin of data packet with short (int16) format
    List<byte> tmpdata = new List<byte>();
    tmpdata.AddRange(BitConverter.GetBytes((short)(buffer.Length + 2)));
    tmpdata.AddRange(buffer);
    buffer = tmpdata.ToArray();
    int size = buffer.Length; //Moved from higher up, now that buffer is a different size

在接收端,您应该有类似的代码 - 循环直到您读取 2 个字节,使用它创建一个 short,这是要接收的总大小,减去 2(老实说,我只是避免添加2 在上面的代码中,并将大小作为大小发送忽略用于对大小进行编码的实际字节),然后再次循环,直到您阅读了整个消息。

【讨论】:

    【解决方案2】:

    如果没有 NetworkStream 或者性能更好,有没有更好的解决方案?

    NetworkStream 充当 Socket 的更高级别包装器,因此您可以直接使用它来做同样的事情:

    var targetStream = new MemoryStream();
    var buffer = new byte[receiveBufferSize];
    int bytesReceived = 0;
    
    while ((bytesReceived = socket.Receive(buffer)) > 0)
    {
        targetStream.Write(buffer, 0, bytesReceived);
    }
    

    Socket 中还有 SendAsyncReceiveAsync 方法,当您需要执行多个并发操作时,它们可以很好地工作。但它们更复杂:

    var receive = new SocketAsyncEventArgs();
    var receiveBuffer = new byte[receiveBufferSize];
    receive.SetBuffer(receiveBuffer, 0, receiveBuffer.Length);
    receive.Completed += HandleReceived;
    
    if (!socket.ReceiveAsync(receive))
    {
        HandleReceived(this, receive);
    }
    

    【讨论】:

      猜你喜欢
      • 2012-12-14
      • 1970-01-01
      • 2015-07-31
      • 1970-01-01
      • 2021-11-19
      • 1970-01-01
      • 1970-01-01
      • 2020-01-09
      • 2018-04-20
      相关资源
      最近更新 更多