Пример #1
0
            private TSocket CreateAcceptSocket(IPEndPoint endPoint, SocketFlags flags)
            {
                int acceptSocketFd = -1;
                int port           = endPoint.Port;

                try
                {
                    bool ipv4 = endPoint.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork;
                    SocketInterop.Socket(ipv4 ? AF_INET : AF_INET6, SOCK_STREAM, IPPROTO_TCP, blocking: false,
                                         out acceptSocketFd).ThrowOnError();

                    TSocket acceptSocket = new TSocket(this, acceptSocketFd, flags, _transportOptions);

                    if (!ipv4)
                    {
                        // Kestrel does mapped ipv4 by default.
                        acceptSocket.SetSocketOption(SOL_IPV6, IPV6_V6ONLY, 0);
                    }
                    if (_transportOptions.ReceiveOnIncomingCpu)
                    {
                        if (_transportThread.CpuId != -1)
                        {
                            if (!acceptSocket.TrySetSocketOption(SOL_SOCKET, SO_INCOMING_CPU, _transportThread.CpuId))
                            {
                                _logger.LogWarning($"Cannot enable SO_INCOMING_CPU for {endPoint}");
                            }
                        }
                    }
                    // Linux: allow bind during linger time
                    acceptSocket.SetSocketOption(SOL_SOCKET, SO_REUSEADDR, 1);
                    // Linux: allow concurrent binds and let the kernel do load-balancing
                    acceptSocket.SetSocketOption(SOL_SOCKET, SO_REUSEPORT, 1);
                    if ((flags & SocketFlags.DeferAccept) != 0)
                    {
                        // Linux: wait up to 1 sec for data to arrive before accepting socket
                        acceptSocket.SetSocketOption(SOL_TCP, TCP_DEFER_ACCEPT, 1);
                    }
                    acceptSocket.ZeroCopyThreshold = LinuxTransportOptions.NoZeroCopy;
                    if (_transportOptions.ZeroCopy && _transportOptions.ZeroCopyThreshold != LinuxTransportOptions.NoZeroCopy)
                    {
                        if (acceptSocket.TrySetSocketOption(SOL_SOCKET, SO_ZEROCOPY, 1))
                        {
                            acceptSocket.ZeroCopyThreshold = _transportOptions.ZeroCopyThreshold;
                        }
                    }

                    var bindResult = acceptSocket.TryBind(endPoint);

                    if (bindResult == PosixResult.EADDRINUSE)
                    {
                        throw new AddressInUseException("Address in use.");
                    }

                    if (bindResult == PosixResult.EADDRNOTAVAIL)
                    {
                        throw new AddressNotAvailableException("Address not available.");
                    }

                    bindResult.ThrowOnError();

                    if (port == 0)
                    {
                        // When testing we want the OS to select a free port
                        port = acceptSocket.GetLocalIPAddress().Port;
                    }

                    acceptSocket.Listen(ListenBacklog);

                    endPoint.Port = port;
                    return(acceptSocket);
                }
                catch
                {
                    if (acceptSocketFd != -1)
                    {
                        IOInterop.Close(acceptSocketFd);
                    }
                    throw;
                }
            }