mirror of
https://github.com/inthehand/32feet.git
synced 2026-10-18 22:44:23 +08:00
106 lines
3.2 KiB
C#
106 lines
3.2 KiB
C#
// 32feet.NET - Personal Area Networking for .NET
|
|
//
|
|
// InTheHand.Net.Sockets.NetworkStream
|
|
//
|
|
// Copyright (c) 2018-2022 In The Hand Ltd, All rights reserved.
|
|
// This source code is licensed under the MIT License
|
|
|
|
using System.Diagnostics;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.IO;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
|
|
namespace InTheHand.Net.Sockets
|
|
{
|
|
/// <exclude/>
|
|
public abstract class NonSocketNetworkStream : NetworkStream
|
|
{
|
|
/// <exclude/>
|
|
public NonSocketNetworkStream() : base(GetAConnectedSocket(), false)
|
|
{
|
|
}
|
|
|
|
internal static Socket GetAConnectedSocket()
|
|
{
|
|
Socket s = SocketPair.GetConnectedSocket();
|
|
Debug.Assert(s != null);
|
|
Debug.Assert(s.Connected);
|
|
return s;
|
|
}
|
|
|
|
|
|
|
|
|
|
}//class
|
|
|
|
internal sealed class SocketPair
|
|
{
|
|
Socket m_cli;
|
|
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields",
|
|
Justification = "m_svr is there to stop the Socket's Finalization.")]
|
|
Socket m_svr;
|
|
static SocketPair m_SocketPair;
|
|
|
|
//--------
|
|
internal static Socket GetConnectedSocket()
|
|
{
|
|
// No need for locking etc here, as it's ok to make one or more (not
|
|
// many hopefully however!) The socket (is meant!) to be only used on
|
|
// initialising the base NetworkStream, so it doesn't matter if the
|
|
// SocketPair is finalized either. Better to create only one, hence
|
|
// why we cache it.
|
|
// Careful of a race between accessing it, it becoming null, and the
|
|
// Finalizer running, so keep a reference locally.
|
|
SocketPair sp = m_SocketPair;
|
|
if (sp == null || !sp.Alive)
|
|
m_SocketPair = sp = SocketPair.Create();
|
|
return sp.m_cli;
|
|
}
|
|
|
|
//--------
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
|
|
internal static SocketPair Create()
|
|
{
|
|
try
|
|
{
|
|
return Create(AddressFamily.InterNetworkV6);
|
|
}
|
|
catch
|
|
{
|
|
return Create(AddressFamily.InterNetwork);
|
|
}
|
|
}
|
|
|
|
internal static SocketPair Create(AddressFamily af)
|
|
{
|
|
return new SocketPair(af);
|
|
}
|
|
|
|
//--------
|
|
private SocketPair(AddressFamily af)
|
|
{
|
|
using (Socket lstnr = new Socket(af, SocketType.Stream, ProtocolType.Unspecified))
|
|
{
|
|
lstnr.Bind(new IPEndPoint(
|
|
af == AddressFamily.InterNetworkV6 ? IPAddress.IPv6Loopback : IPAddress.Loopback, 0));
|
|
lstnr.Listen(1);
|
|
EndPoint svrEp = lstnr.LocalEndPoint;
|
|
m_cli = new Socket(svrEp.AddressFamily, lstnr.SocketType, lstnr.ProtocolType);
|
|
m_cli.Connect(svrEp);
|
|
m_svr = lstnr.Accept();
|
|
}
|
|
}
|
|
|
|
//--------
|
|
private bool Alive
|
|
{
|
|
get
|
|
{
|
|
return m_cli != null // just for safety, shouldn't occur
|
|
&& m_cli.Connected;
|
|
}
|
|
}
|
|
}
|
|
}
|