Пример #1
0
        public unsafe PosixResult TryReceive(ArraySegment <byte> buffer)
        {
            ValidateSegment(buffer);
            fixed(byte *buf = buffer.Array)
            {
                IOVector ioVector = new IOVector()
                {
                    Base = buf + buffer.Offset, Count = (void *)buffer.Count
                };

                return(SocketInterop.Receive(this, &ioVector, 1));
            }
        }
Пример #2
0
        private static unsafe Exception Receive(int fd, int availableBytes, ref WritableBuffer wb)
        {
            int ioVectorLength = availableBytes <= wb.Buffer.Length ? 1 :
                                 Math.Min(1 + (availableBytes - wb.Buffer.Length + MaxPooledBlockLength - 1) / MaxPooledBlockLength, MaxIOVectorReceiveLength);
            var ioVectors = stackalloc IOVector[ioVectorLength];
            var allocated = 0;

            var advanced      = 0;
            int ioVectorsUsed = 0;

            for (; ioVectorsUsed < ioVectorLength; ioVectorsUsed++)
            {
                wb.Ensure(1);
                var   memory = wb.Buffer;
                var   length = memory.Length;
                void *pointer;
                wb.Buffer.TryGetPointer(out pointer);

                ioVectors[ioVectorsUsed].Base  = pointer;
                ioVectors[ioVectorsUsed].Count = (void *)length;
                allocated += length;

                if (allocated >= availableBytes)
                {
                    // Every Memory (except the last one) must be filled completely.
                    ioVectorsUsed++;
                    break;
                }

                wb.Advance(length);
                advanced += length;
            }
            var expectedMin = Math.Min(availableBytes, allocated);

            // Ideally we get availableBytes in a single receive
            // but we are happy if we get at least a part of it
            // and we are willing to take {MaxEAgainCount} EAGAINs.
            // Less data could be returned due to these reasons:
            // * TCP URG
            // * packet was not placed in receive queue (race with FIONREAD)
            // * ?
            const int MaxEAgainCount = 10;
            var       eAgainCount    = 0;
            var       received       = 0;

            do
            {
                var result = SocketInterop.Receive(fd, ioVectors, ioVectorsUsed);
                if (result.IsSuccess)
                {
                    received += result.Value;
                    if (received >= expectedMin)
                    {
                        // We made it!
                        wb.Advance(received - advanced);
                        return(null);
                    }
                    eAgainCount = 0;
                    // Update ioVectors to match bytes read
                    var skip = result.Value;
                    for (int i = 0; (i < ioVectorsUsed) && (skip > 0); i++)
                    {
                        var length  = (int)ioVectors[i].Count;
                        var skipped = Math.Min(skip, length);
                        ioVectors[i].Count = (void *)(length - skipped);
                        ioVectors[i].Base  = (byte *)ioVectors[i].Base + skipped;
                        skip -= skipped;
                    }
                }
                else if (result == PosixResult.EAGAIN || result == PosixResult.EWOULDBLOCK)
                {
                    eAgainCount++;
                    if (eAgainCount == MaxEAgainCount)
                    {
                        return(new NotSupportedException("Too many EAGAIN, unable to receive available bytes."));
                    }
                }
                else if (result == PosixResult.ECONNRESET)
                {
                    return(new ConnectionResetException(result.ErrorDescription(), result.AsException()));
                }
                else
                {
                    return(result.AsException());
                }
            } while (true);
        }
Пример #3
0
 public unsafe PosixResult TryReceive(IOVector *ioVectors, int ioVectorLen)
 {
     return(SocketInterop.Receive(this, ioVectors, ioVectorLen));
 }