* Updates for TcpClient project

* Remove TcpTest

Ops, this was meant to be removed and used a as basis for sample

* Updated as per review

* Fix connect issue

* Update readme & check code formatting

* Changes to keep SonarCloud happy

* Update README.md

* Update project to latest to include new streams assembly

* Update nanoframework.System.Net.Sockets.TcpClient.nuspec
This commit is contained in:
Adrian Soundy 2022-02-23 23:08:39 +13:00 коммит произвёл GitHub
Родитель c36b03b1d4
Коммит e26cbd9b37
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
21 изменённых файлов: 1079 добавлений и 260 удалений

32
.github/workflows/update-dependencies.yml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,32 @@
# Copyright (c) .NET Foundation and Contributors
# See LICENSE file in the project root for full license information.
# This workflow will periodically check .NET nanoFramework dependencies and updates them in the repository it's running.
name: Daily update dependencies
on:
schedule:
# At 00:00 UTC every day.
- cron: '00 00 * * *'
repository_dispatch:
types: update-dependencies
defaults:
run:
shell: pwsh
jobs:
update-dotnet-preview:
name: Update .NET nanoFramework dependencies
timeout-minutes: 15
runs-on: windows-latest
env:
GITHUB_TOKEN: ${{ github.token }}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Update dependencies
uses: nanoframework/nanodu@v1
with:
solutionsToCheck: 'nanoframework.System.Net.Sockets.TcpClient.sln'

Просмотреть файл

@ -0,0 +1,13 @@
user=nanoframework
project=System.Net.Sockets.TcpClient
issues=false
add_issues_wo_labels=false
add_pr_wo_labels=false
add_issues_wo_labels=false
filter_issues_by_milestone=false
exclude_labels=Area: Config-and-Build,Area: Infrastructure-and-Organization,reverted
enhancement_labels=Type: enhancement
bug_labels=Type: bug
merge_prefix=**Documentation and other chores:**
unreleased_label=**Changes available only in 'Preview' NuGet packages:**
author=false

204
README.md
Просмотреть файл

@ -1 +1,203 @@
# System.Net.Sockets.TcpClient

[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=nanoframework_System.Net.Sockets.TcpClient&metric=alert_status)](https://sonarcloud.io/dashboard?id=nanoframework_System.Net.Sockets.TcpClient) [![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=nanoframework_System.Net.Sockets.TcpClient&metric=reliability_rating)](https://sonarcloud.io/dashboard?id=nanoframework_System.Net.Sockets.TcpClient) [![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![NuGet](https://img.shields.io/nuget/dt/nanoFramework.System.Net.Sockets.TcpClient.svg?label=NuGet&style=flat&logo=nuget)](https://www.nuget.org/packages/nanoFramework.System.Net.Sockets.TcpClient/) [![#yourfirstpr](https://img.shields.io/badge/first--timers--only-friendly-blue.svg)](https://github.com/nanoframework/Home/blob/main/CONTRIBUTING.md) [![Discord](https://img.shields.io/discord/478725473862549535.svg?logo=discord&logoColor=white&label=Discord&color=7289DA)](https://discord.gg/gCyBu8T)
![nanoFramework logo](https://raw.githubusercontent.com/nanoframework/Home/main/resources/logo/nanoFramework-repo-logo.png)
-----
# System.Net.Sockets.TcpClient
This API implements the TcpListener and TcpClient classes with a pattern similar to the official .NET equivalent. [System.NET.Sockets.TcpClient](https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.TcpClient).
These are wrapper classes for the Socket when using TCP connections.
The nanoframework implementation of TcpClient doesn't include the asynchronous methods and the Connected property.
## Build status
| Component | Build Status | NuGet Package |
|:-|---|---|
| nanoFramework.System.Net.Sockets.TcpClient | [![Build Status](https://dev.azure.com/nanoframework/System.Net.Sockets.TcpClient/_apis/build/status/System.Net.Sockets.TcpClient?branchName=main)](https://dev.azure.com/nanoframework/System.Net.Sockets.TcpClient/_build/latest?definitionId=91&branchName=main) | [![NuGet](https://img.shields.io/nuget/v/nanoFramework.System.Net.Sockets.TcpClient.svg?label=NuGet&style=flat&logo=nuget)](https://www.nuget.org/packages/nanoFramework.System.Net.Sockets.TcpClient/) |
| nanoFramework.System.Net.Sockets.TcpClient (preview) | [![Build Status](https://dev.azure.com/nanoframework/System.Net.Sockets.TcpClient/_apis/build/status/System.Net.Sockets.TcpClient?branchName=develop)](https://dev.azure.com/nanoframework/System.Net.Sockets.TcpClient/_build/latest?definitionId=91&branchName=develop) | [![NuGet](https://img.shields.io/nuget/vpre/nanoFramework.System.Net.Sockets.TcpClient.svg?label=NuGet&style=flat&logo=nuget)](https://www.nuget.org/packages/nanoFramework.System.Net.Sockets.TcpClient/) |
## Usage
**Important:** Obviously this requires a working network connection. Please check the examples with the Network Helpers on how to connect to a network. For example see the [Networking sample pack](https://github.com/nanoframework/Samples/tree/main/samples/Networking)
The `TcpListener` class provides simple methods for creating a listening socket to accept incoming TCP connections and the `TcpClient` provides methods for connecting and communicating on a TCP connection.
### Samples
Samples for `TcpListener` and `TcpClient` are present in the [nanoFramework Sample repository](https://github.com/nanoframework/Samples).
### Listening for incoming connections
The following codes shows how to set up a Listening socket and to accept connections as a TcpClient on the 1234 port.
```csharp
TcpListener listener = new TcpListener(IPAddress.Any, 1234);
// Start listening for incoming connections
listener.Start();
while (true)
{
try
{
// Wait for incoming connections
TcpClient client = listener.AcceptTcpClient();
NetworkStream stream = client.GetStream();
Byte[] bytes = new Byte[256];
int i;
// Wait for incoming data and echo back
while((i = stream.Read(bytes, 0, bytes.Length))!=0)
{
// Do something with data ?
stream.Write(bytes, 0, i);
}
// Shutdown connection
client.Close();
}
catch(Exception ex)
{
Debug.WriteLine($"Exception:-{ex.Message}");
}
}
```
If you want to handle more then one simultaneous connection then a separate worker thread can be started.
```csharp
TcpListener listener = new TcpListener(IPAddress.Any, 1234);
// Start listening for incoming connections with backlog
listener.Start(2);
while (true)
{
try
{
// Wait for incoming connections
TcpClient client = listener.AcceptTcpClient();
// Start thread to handle connection
Thread worker = new Thread(() => WorkerThread(client));
worker.Start();
}
catch(Exception ex)
{
Debug.WriteLine($"Exception:-{ex.Message}");
}
}
```
Worker Thread for handling the TcpClient connection for TcpListener example.
```csharp
private static void WorkerThread(TcpClient client)
{
try
{
NetworkStream stream = client.GetStream();
Byte[] bytes = new Byte[256];
int i;
// Loop reading data until connection closed
while((i = stream.Read(bytes, 0, bytes.Length))!=0)
{
// Do something with data ?
// Write back received data bytes to stream
stream.Write(bytes, 0, i);
}
}
catch(Exception ex)
{
Debug.WriteLine($"Exception:-{ex.Message}");
}
finally
{
// Shutdown connection
client.Close();
}
}
```
### TcpClient
The TcpClient can also be used to initiate a connection passing in the hostname/port or IPEndPoint.
Maybe connecting to another nanoFramework device which is listening for connections.
```csharp
TcpClient client = new TcpClient()
try
{
client.Connect(hostname, port)
NetworkStream stream = client.GetStream();
// Write / Read data on stream
// for example Write 'ABC' and wait for response
byte[] writeData = new byte[] { 0x41, 0x42, 0x43 };
stream.Write(writeData, 0, writeData.Length);
// Read reply and close
byte[] buffer = new byte[1024];
int bytesRead = stream.Read(buffer, 0, buffer.Length);
// Process read data ?
}
catch(SocketException sx)
{
Console.WriteLine($"Socket error:{sx.ErrorCode} exception:{sx.Message}");
}
finally
{
client.Close();
}
```
For secure connections a `SslStream` can be used.
```csharp
client.Connect(HostName, 443);
// Create SSlStream from underlying SOcket
SslStream stream = new SslStream(client.Client);
// Don't verify Server certificate for this sample code
stream.SslVerification = SslVerification.NoVerification;
stream.AuthenticateAsClient(HostName, SslProtocols.Tls12);
// stream.Write() or stream.Read()
```
## Feedback and documentation
For documentation, providing feedback, issues and finding out how to contribute please refer to the [Home repo](https://github.com/nanoframework/Home).
Join our Discord community [here](https://discord.gg/gCyBu8T).
## Credits
The list of contributors to this project can be found at [CONTRIBUTORS](https://github.com/nanoframework/Home/blob/main/CONTRIBUTORS.md).
## License
The **nanoFramework** Class Libraries are licensed under the [MIT license](LICENSE.md).
## Code of Conduct
This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behaviour in our community.
For more information see the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/code-of-conduct).
### .NET Foundation
This project is supported by the [.NET Foundation](https://dotnetfoundation.org).

257
Tests/ConnectionTests.cs Normal file
Просмотреть файл

@ -0,0 +1,257 @@
//
// Copyright (c) .NET Foundation and Contributors
// Portions Copyright (c) Microsoft Corporation. All rights reserved.
// See LICENSE file in the project root for full license information.
//
//
using nanoFramework.TestFramework;
using System;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace NFUnitTests
{
[TestClass]
public class ConnectionTests
{
const int TESTPORT = 1234;
static byte[] _testData = new byte[256];
[Setup]
public void Initialize()
{
// Remove this line to run hardware tests
Assert.SkipTest("No Network");
Debug.WriteLine("TcpListener.TcpClient connection Tests initialized.");
// Init test data
for (int i = 0; i < _testData.Length; i++)
{
_testData[i] = (byte)i;
}
}
[TestMethod]
public void ListenAndConnect()
{
const int MaxConnections = 4;
bool testRunning = true;
int workerID = 1;
int connectionAccepted = 0;
Thread[] workers = new Thread[MaxConnections];
// Create listener on Loop back address
TcpListener listener = CreateListener();
listener.Start(4);
// Start some Threads to connect to Listener and Send/Receive data
for (int sndCount = 0; sndCount < MaxConnections; sndCount++)
{
Thread Sender1 = new Thread(() => SenderThread(100 + workerID++));
Sender1.Start();
}
while (testRunning)
{
// All connections accepted, break accept loop
if (connectionAccepted >= MaxConnections)
{
break;
}
try
{
TcpClient client = listener.AcceptTcpClient();
workers[connectionAccepted] = new Thread(() => WorkerThread(client, workerID++));
workers[connectionAccepted].Start();
connectionAccepted++;
}
catch (Exception ex)
{
Debug.WriteLine($"Exception:-{ex.Message}");
Thread.Sleep(500);
}
}
listener.Stop();
Debug.WriteLine($"listener stopped");
Debug.WriteLine($"Waiting for Workers to end");
bool WorkersRunning = true;
while (WorkersRunning)
{
// Wait for all Worker threads to close
WorkersRunning = false;
foreach (Thread thd in workers)
{
if (thd.IsAlive)
{
WorkersRunning = true;
break;
}
}
Thread.Sleep(10);
}
Debug.WriteLine($"All workers ended");
}
public static void SenderThread(int workerID)
{
// IPV4 address
IPEndPoint endPoint = new IPEndPoint(IPAddress.Loopback, TESTPORT);
TcpClient sender = new TcpClient();
sender.Connect(endPoint);
NetworkStream stream = sender.GetStream();
for (int count = 1; count < 20; count++)
{
int length = count * 2;
// Write header
stream.WriteByte(0xfc);
stream.WriteByte((byte)(length & 0xff)); // Low length
stream.WriteByte((byte)((length >> 8) & 0xff)); // High length
byte[] buffer = new byte[length];
// fill buffer with test data
Array.Copy(_testData, count, buffer, 0, length);
stream.Write(buffer, 0, length);
Array.Clear(buffer, 0, length);
int sync = stream.ReadByte();
Assert.True(sync == 0xfc, $"{workerID} count={count} read sync != 0xfc => {sync}");
int lenL = stream.ReadByte();
int lenH = stream.ReadByte();
int dataLength = (lenH << 8) + lenL;
Assert.True(dataLength == length, $"{workerID} Sender rx invalid length {dataLength} should be {length}");
int readBytes = stream.Read(buffer, 0, length);
Assert.True(readBytes == length, $"{workerID} Read bytes:{readBytes} <> requested length:{length}");
// Validate buffer
for (int i = 0; i < length; i++)
{
Assert.False(buffer[i] != _testData[i + count], $"Received data not same as send, position:{i} {buffer[i]}!={_testData[i + count]}");
}
Debug.WriteLine($"{workerID}: Send/Receive count:{count} complete");
}
stream.Close();
sender.Dispose();
}
/// <summary>
/// Thread to echo back data received
/// Data in format 0xFC, length:uint16, data bytes .......
/// </summary>
/// <param name="client">TcpClient</param>
/// <param name="workerID">ID for logging</param>
public static void WorkerThread(TcpClient client, int workerID)
{
Debug.WriteLine($" {workerID}:Client connected to {client.Client.RemoteEndPoint.ToString()}");
NetworkStream stream = client.GetStream();
// Set RX time outs on stream
stream.ReadTimeout = 10000;
// Netstream.Read will return straight away if there is no data to read
while (true)
{
try
{
// Wait for first byte
// This will sit on Read until 1 byte of data available giving time to other threads
int syncbyte = stream.ReadByte();
if (syncbyte == -1)
{
Debug.WriteLine($"{workerID}:Connection closed");
break;
}
Assert.True(syncbyte == 0xfc, $"{workerID}:Sync byte != FC => {syncbyte}");
int lenL = stream.ReadByte();
int lenH = stream.ReadByte();
int dataLength = (lenH << 8) + lenL;
Assert.True(dataLength <= 512, $"{workerID}:Invalid length {dataLength}");
byte[] buffer = new byte[dataLength];
// Then read the rest of data in loop
int bufferPos = 0;
int bytesToRead = 0;
while (bytesToRead < dataLength)
{
int dataAv = client.Available;
if (dataAv > 0)
{
int bytesRead = stream.Read(buffer, bufferPos, dataAv);
bufferPos += bytesRead;
bytesToRead += bytesRead;
}
else
{
Thread.Sleep(0);
}
}
Assert.True(bytesToRead == dataLength, $"{workerID}:Data read != availableInvalid length {dataLength}");
stream.WriteByte(0xfc);
stream.WriteByte((byte)(dataLength & 0xff)); // Low length
stream.WriteByte((byte)((dataLength >> 8) & 0xff)); // High length
// Echo data back
stream.Write(buffer, 0, dataLength);
}
catch (Exception ex)
{
Debug.WriteLine($"{workerID}:Worker exception {ex.Message}");
break;
}
} // while
client.Close();
Debug.WriteLine($"{workerID}:Worker closed");
}
/// <summary>
/// Create a TcpListener and check
/// </summary>
/// <returns>TcpListener</returns>
public TcpListener CreateListener()
{
TcpListener listener = new TcpListener(IPAddress.Loopback, TESTPORT);
Assert.NotNull(listener);
Debug.WriteLine("TcpListener created.");
Assert.Equal(((IPEndPoint)listener.LocalEndpoint).Port, TESTPORT, "Wrong port on Listener");
Assert.Equal((int)((IPEndPoint)listener.LocalEndpoint).AddressFamily, (int)AddressFamily.InterNetwork, "Wrong address family");
Assert.True(((IPEndPoint)listener.LocalEndpoint).Address == IPAddress.Loopback, "Wrong IP address");
return listener;
}
}
}

Просмотреть файл

@ -0,0 +1,31 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyCopyright("Copyright (c) 2021 nanoFramework contributors")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

97
Tests/Tests.nfproj Normal file
Просмотреть файл

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<NanoFrameworkProjectSystemPath>$(MSBuildExtensionsPath)\nanoFramework\v1.0\</NanoFrameworkProjectSystemPath>
</PropertyGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props')" />
<ItemGroup>
<ProjectCapability Include="TestContainer" />
</ItemGroup>
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectTypeGuids>{11A8DD76-328B-46DF-9F39-F559912D0360};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<ProjectGuid>a0df7a0b-8dcd-4cfa-a29f-49f0c2400a07</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<FileAlignment>512</FileAlignment>
<RootNamespace>NFUnitTests</RootNamespace>
<AssemblyName>NFUnitTest</AssemblyName>
<IsCodedUITest>False</IsCodedUITest>
<IsTestProject>true</IsTestProject>
<TestProjectType>UnitTest</TestProjectType>
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
</PropertyGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
<PropertyGroup>
<RunSettingsFilePath>$(MSBuildProjectDirectory)\nano.runsettings</RunSettingsFilePath>
</PropertyGroup>
<ItemGroup>
<Compile Include="ConnectionTests.cs" />
<Compile Include="UnitTestListener.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="mscorlib, Version=1.12.0.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\packages\nanoFramework.CoreLibrary.1.12.0-preview.9\lib\mscorlib.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="nanoFramework.Runtime.Events, Version=1.10.0.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\packages\nanoFramework.Runtime.Events.1.10.0-preview.8\lib\nanoFramework.Runtime.Events.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="nanoFramework.System.Text, Version=1.1.3.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\packages\nanoFramework.System.Text.1.1.3-preview.15\lib\nanoFramework.System.Text.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="nanoFramework.TestFramework, Version=1.0.178.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\packages\nanoFramework.TestFramework.1.0.178\lib\nanoFramework.TestFramework.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="nanoFramework.UnitTestLauncher, Version=0.0.0.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\packages\nanoFramework.TestFramework.1.0.178\lib\nanoFramework.UnitTestLauncher.exe</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="System.IO.Streams, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\packages\nanoFramework.System.IO.Streams.1.0.0-preview.12\lib\System.IO.Streams.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="System.Net, Version=1.8.0.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\packages\nanoFramework.System.Net.1.8.0-preview.29\lib\System.Net.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="System.Threading, Version=1.0.4.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\packages\nanoFramework.System.Threading.1.0.4-preview.16\lib\System.Threading.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
</ItemGroup>
<ItemGroup>
<None Include="nano.runsettings" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\nanoframework.System.Net.Sockets.TcpClient\nanoframework.System.Net.Sockets.TcpClient.nfproj" />
</ItemGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets')" />
<!-- MANUAL UPDATE HERE -->
<Import Project="..\packages\nanoFramework.TestFramework.1.0.172\build\nanoFramework.TestFramework.targets" Condition="Exists('..\packages\nanoFramework.TestFramework.1.0.172\build\nanoFramework.TestFramework.targets')" />
<ProjectExtensions>
<ProjectCapabilities>
<ProjectConfigurationsDeclaredAsItems />
</ProjectCapabilities>
</ProjectExtensions>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<WarningText>Update the Import path in nfproj to the correct nanoFramework.TestFramework NuGet package folder.</WarningText>
</PropertyGroup>
<Warning Condition="!Exists('..\packages\nanoFramework.TestFramework.1.0.172\build\nanoFramework.TestFramework.targets')" Text="'$(WarningText)'" />
</Target>
</Project>

75
Tests/UnitTestListener.cs Normal file
Просмотреть файл

@ -0,0 +1,75 @@
//
// Copyright (c) .NET Foundation and Contributors
// Portions Copyright (c) Microsoft Corporation. All rights reserved.
// See LICENSE file in the project root for full license information.
//
using nanoFramework.TestFramework;
using System;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
namespace NFUnitTests
{
[TestClass]
public class TestTcpListener
{
private const int TESTPORT = 1234;
[Setup]
public void Initialize()
{
// Remove this line to run hardware tests
Assert.SkipTest("No Network");
Debug.WriteLine("TcpListener Tests initialized.");
}
[TestMethod]
public void CreateAndStart()
{
Debug.WriteLine("CreateAndStart.");
TcpListener listener = CreateListener();
listener.Start(1);
// Get underlying socket
Socket listenSocket = listener.Server;
Assert.NotNull(listenSocket, "Listen socket null");
listener.Stop();
listener = null;
}
[TestMethod]
public void StateExceptionChecks()
{
TcpListener listener = CreateListener();
Assert.Throws(typeof(InvalidOperationException), () => { listener.Stop(); }, "No exception when stopping and not started");
listener.Start(1);
Assert.Throws(typeof(InvalidOperationException), () => { listener.Start(1); }, "No exception when starting and already started");
listener.Stop();
}
public TcpListener CreateListener()
{
TcpListener listener = new TcpListener(IPAddress.Loopback, TESTPORT);
Assert.NotNull(listener);
Debug.WriteLine("TcpListener created.");
Assert.Equal(((IPEndPoint)listener.LocalEndpoint).Port, TESTPORT, "Wrong port on Listener");
Assert.Equal((int)((IPEndPoint)listener.LocalEndpoint).AddressFamily, (int)AddressFamily.InterNetwork, "Wrong address family");
Assert.True(((IPEndPoint)listener.LocalEndpoint).Address == IPAddress.Loopback, "Wrong IP address");
return listener;
}
}
}

14
Tests/nano.runsettings Normal file
Просмотреть файл

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<!-- Configurations that affect the Test Framework -->
<RunConfiguration>
<MaxCpuCount>1</MaxCpuCount>
<ResultsDirectory>.\TestResults</ResultsDirectory><!-- Path relative to solution directory -->
<TestSessionTimeout>120000</TestSessionTimeout><!-- Milliseconds -->
<TargetFrameworkVersion>Framework40</TargetFrameworkVersion>
</RunConfiguration>
<nanoFrameworkAdapter>
<Logging>None</Logging>
<IsRealHardware>False</IsRealHardware>
</nanoFrameworkAdapter>
</RunSettings>

10
Tests/packages.config Normal file
Просмотреть файл

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="nanoFramework.CoreLibrary" version="1.12.0-preview.9" targetFramework="netnanoframework10" />
<package id="nanoFramework.Runtime.Events" version="1.10.0-preview.8" targetFramework="netnanoframework10" />
<package id="nanoFramework.System.IO.Streams" version="1.0.0-preview.12" targetFramework="netnanoframework10" />
<package id="nanoFramework.System.Net" version="1.8.0-preview.29" targetFramework="netnanoframework10" />
<package id="nanoFramework.System.Text" version="1.1.3-preview.15" targetFramework="netnanoframework10" />
<package id="nanoFramework.System.Threading" version="1.0.4-preview.16" targetFramework="netnanoframework10" />
<package id="nanoFramework.TestFramework" version="1.0.178" targetFramework="netnanoframework10" developmentDependency="true" />
</packages>

Просмотреть файл

@ -1,10 +1,27 @@
# Copyright (c) .NET Foundation and Contributors
# See LICENSE file in the project root for full license information.
trigger:
branches:
include: [main, develop, "release-*" ]
include:
- main
- develop
- release-*
paths:
exclude: [README.md, LICENSE.md, NuGet.Config, .github_changelog_generator, .gitignore]
exclude:
- .github_changelog_generator
- .gitignore
- CHANGELOG.md
- CODE_OF_CONDUCT.md
- LICENSE.md
- README.md
- NuGet.Config
- assets/*
- config/*
- .github/*
tags:
include: ["v*"]
include:
- v*
# PR always trigger build
pr:
@ -17,80 +34,29 @@ resources:
type: github
name: nanoframework/nf-tools
endpoint: nanoframework
jobs:
##############################
- job: Build_Library
condition: or( eq(variables['UPDATE_DEPENDENTS'], 'false'), eq(variables['StartReleaseCandidate'], 'true') )
pool:
vmImage: 'windows-2019'
pool:
vmImage: 'windows-latest'
variables:
DOTNET_NOLOGO: true
solution: 'nanoFramework.System.Net.Sockets.TcpClient.sln'
buildPlatform: 'Any CPU'
buildConfiguration: 'Release'
nugetPackageName: 'nanoFramework.System.Net.Sockets.TcpClient'
variables:
DOTNET_NOLOGO: true
solution: 'nanoFramework.System.Net.Sockets.TcpClient.sln'
buildPlatform: 'Any CPU'
buildConfiguration: 'Release'
nugetPackageName: 'nanoFramework.System.Net.Sockets.TcpClient'
steps:
steps:
# step from template @ nf-tools repo
# all build, update and publish steps
- template: azure-pipelines-templates/class-lib-build.yml@templates
parameters:
sonarCloudProject: 'nanoframework_lib-nanoFramework.System.Net.Sockets.TcpClient'
runUnitTests: false
unitTestRunsettings: '$(System.DefaultWorkingDirectory)\Tests\SocketTests\nano.runsettings'
# step from template @ nf-tools repo
# build steps only
- template: azure-pipelines-templates/class-lib-build.yml@templates
parameters:
sonarCloudProject: 'nanoframework_System.Net.Sockets.TcpClient'
##############################
- job: Update_Dependents
condition: or( and( succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'), eq(variables['StartReleaseCandidate'], 'false') ), and( succeeded(), contains(variables['getCommitMessage.COMMIT_MESSAGE'], '***UPDATE_DEPENDENTS***'), eq(variables['StartReleaseCandidate'], 'false') ), eq(variables['UPDATE_DEPENDENTS'], 'true') )
dependsOn:
- Build_Library
pool:
vmImage: 'windows-2019'
variables:
DOTNET_NOLOGO: true
steps:
- checkout: none
# update dependents
- template: azure-pipelines-templates/update-dependents.yml@templates
parameters:
repositoriesToUpdate: |
System.Net.Http
System.Net.WebSockets
System.Device.WiFi
nanoFramework.m2mqtt
nanoFramework.Azure.Devices
##################################
# report build failure to Discord
- job: Report_Build_Failure
condition: or( failed('Build_Library'), failed('Update_Dependents'))
dependsOn:
- Build_Library
- Update_Dependents
pool:
vmImage: 'windows-2019'
steps:
- checkout: self
# step from template @ nf-tools repo
# report error
- template: azure-pipelines-templates/discord-webhook-task.yml@templates
parameters:
status: 'failure'
webhookUrl: '$(DiscordWebhook)'
message: ''
# step from template @ nf-tools repo
# report error
- template: azure-pipelines-templates/discord-webhook-task.yml@templates
parameters:
status: 'failure'
webhookUrl: '$(DiscordWebhook)'
message: ''

14
config/SignClient.json Normal file
Просмотреть файл

@ -0,0 +1,14 @@
{
"SignClient": {
"AzureAd": {
"AADInstance": "https://login.microsoftonline.com/",
"ClientId": "c248d68a-ba6f-4aa9-8a68-71fe872063f8",
"TenantId": "16076fdc-fcc1-4a15-b1ca-32c9a255900e"
},
"Service": {
"Url": "https://codesign.dotnetfoundation.org/",
"ResourceId": "https://SignService/3c30251f-36f3-490b-a955-520addb85001"
}
}
}

1
config/filelist.txt Normal file
Просмотреть файл

@ -0,0 +1 @@
**/nanoFramework.System.Net.Sockets.TcpClient.*

Просмотреть файл

@ -1,40 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
<id>nanoframework.System.Net.Sockets.TcpClient</id>
<version>$version$</version>
<title>nanoframework.System.Net.Sockets.TcpClient</title>
<authors>nanoFramework project contributors</authors>
<owners>nanoFramework,dotnetfoundation</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="file">LICENSE.md</license>
<releaseNotes>
</releaseNotes>
<readme>docs\README.md</readme>
<developmentDependency>false</developmentDependency>
<projectUrl>https://github.com/nanoframework/System.Net.Sockets.TcpClient</projectUrl>
<icon>images\nf-logo.png</icon>
<repository type="git" url="https://github.com/nanoframework/System.Net.Sockets.TcpClient" commit="$commit$" />
<copyright>Copyright (c) .NET Foundation and Contributors</copyright>
<description>This package includes the .NET nanoFramework System.Net assembly for .NET nanoFramework C# projects.
This package requires a target with System.Net v$nativeVersion$ (checksum $checksum$).</description>
<tags>nanoFramework C# csharp netmf netnf nanoFramework.System.Net</tags>
<dependencies>
<dependency id="nanoFramework.CoreLibrary" version="1.12.0-preview.5" />
<dependency id="nanoFramework.Runtime.Events" version="1.10.0-preview.6" />
<dependency id="nanoFramework.System.Text" version="1.1.3-preview.13" />
<dependency id="nanoFramework.System.Threading" version="1.0.4-preview.14" />
</dependencies>
</metadata>
<files>
<file src="nanoFramework.System.Net.Sockets.TcpClient\bin\Release\System.Net.dll" target="lib\System.Net.Sockets.TcpClient.dll" />
<file src="nanoFramework.System.Net.Sockets.TcpClient\bin\Release\System.Net.pdb" target="lib\System.Net.Sockets.TcpClient.pdb" />
<file src="nanoFramework.System.Net.Sockets.TcpClient\bin\Release\System.Net.pdbx" target="lib\System.Net.Sockets.TcpClient.pdbx" />
<file src="nanoFramework.System.Net.Sockets.TcpClient\bin\Release\System.Net.pe" target="lib\System.Net.Sockets.TcpClient.pe" />
<file src="nanoFramework.System.Net.Sockets.TcpClient\bin\Release\System.Net.xml" target="lib\System.Net.Sockets.TcpClient.xml" />
<file src="assets\readme.txt" target="" />
<file src="README.md" target="docs\" />
<file src="assets\nf-logo.png" target="images" />
<file src="LICENSE.md" target="" />
</files>
<metadata>
<id>nanoframework.System.Net.Sockets.TcpClient</id>
<version>$version$</version>
<title>nanoframework.System.Net.Sockets.TcpClient</title>
<authors>nanoFramework project contributors</authors>
<owners>nanoFramework,dotnetfoundation</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="file">LICENSE.md</license>
<releaseNotes>
</releaseNotes>
<readme>docs\README.md</readme>
<developmentDependency>false</developmentDependency>
<projectUrl>https://github.com/nanoframework/System.Net.Sockets.TcpClient</projectUrl>
<icon>images\nf-logo.png</icon>
<repository type="git" url="https://github.com/nanoframework/System.Net.Sockets.TcpClient" commit="$commit$" />
<copyright>Copyright (c) .NET Foundation and Contributors</copyright>
<description>
This package includes the .NET nanoFramework System.Net assembly for .NET nanoFramework C# projects.
This package requires a target with System.Net v$nativeVersion$ (checksum $checksum$).
</description>
<tags>nanoFramework C# csharp netmf netnf nanoFramework.System.Net</tags>
<dependencies>
<dependency id="nanoFramework.CoreLibrary" version="1.12.0-preview.9" />
<dependency id="nanoFramework.Runtime.Events" version="1.10.0-preview.8" />
<dependency id="nanoFramework.System.IO.Streams" version="1.0.0-preview.12" />
<dependency id="nanoFramework.System.Net" version="1.8.0-preview.29" />
<dependency id="nanoFramework.System.Text" version="1.1.3-preview.15" />
<dependency id="nanoFramework.System.Threading" version="1.0.4-preview.16" />
</dependencies>
</metadata>
<files>
<file src="nanoFramework.System.Net.Sockets.TcpClient\bin\Release\System.Net.dll" target="lib\System.Net.Sockets.TcpClient.dll" />
<file src="nanoFramework.System.Net.Sockets.TcpClient\bin\Release\System.Net.pdb" target="lib\System.Net.Sockets.TcpClient.pdb" />
<file src="nanoFramework.System.Net.Sockets.TcpClient\bin\Release\System.Net.pdbx" target="lib\System.Net.Sockets.TcpClient.pdbx" />
<file src="nanoFramework.System.Net.Sockets.TcpClient\bin\Release\System.Net.pe" target="lib\System.Net.Sockets.TcpClient.pe" />
<file src="nanoFramework.System.Net.Sockets.TcpClient\bin\Release\System.Net.xml" target="lib\System.Net.Sockets.TcpClient.xml" />
<file src="assets\readme.txt" target="" />
<file src="README.md" target="docs\" />
<file src="assets\nf-logo.png" target="images" />
<file src="LICENSE.md" target="" />
</files>
</package>

Просмотреть файл

@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.32002.261
MinimumVisualStudioVersion = 10.0.40219.1
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "nanoframework.System.Net.Sockets.TcpClient", "nanoframework.System.Net.Sockets.TcpClient\nanoframework.System.Net.Sockets.TcpClient.nfproj", "{1D0F04E3-6AB6-4DE0-88D0-5E30F6F5719B}"
EndProject
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "Tests", "Tests\Tests.nfproj", "{A0DF7A0B-8DCD-4CFA-A29F-49F0C2400A07}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -17,6 +19,12 @@ Global
{1D0F04E3-6AB6-4DE0-88D0-5E30F6F5719B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1D0F04E3-6AB6-4DE0-88D0-5E30F6F5719B}.Release|Any CPU.Build.0 = Release|Any CPU
{1D0F04E3-6AB6-4DE0-88D0-5E30F6F5719B}.Release|Any CPU.Deploy.0 = Release|Any CPU
{A0DF7A0B-8DCD-4CFA-A29F-49F0C2400A07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0DF7A0B-8DCD-4CFA-A29F-49F0C2400A07}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0DF7A0B-8DCD-4CFA-A29F-49F0C2400A07}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{A0DF7A0B-8DCD-4CFA-A29F-49F0C2400A07}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0DF7A0B-8DCD-4CFA-A29F-49F0C2400A07}.Release|Any CPU.Build.0 = Release|Any CPU
{A0DF7A0B-8DCD-4CFA-A29F-49F0C2400A07}.Release|Any CPU.Deploy.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

Просмотреть файл

@ -12,13 +12,10 @@ namespace System.Net.Sockets
/// </summary>
public class LingerOption
{
bool _enabled;
int _lingerTime;
/// <summary>
/// Initializes a new instance of the<see cref='Sockets.LingerOption'
/// Initializes a new instance of the <see cref='Sockets.LingerOption'/>
/// </summary>
/// <param name="enable">Enable or Disable option.</param>
/// <param name="enable">Enable or disable option.</param>
/// <param name="seconds">Number of seconds to linger after close.</param>
public LingerOption(bool enable, int seconds)
{
@ -29,11 +26,11 @@ namespace System.Net.Sockets
/// <summary>
/// Enables or disables lingering after close.
/// </summary>
public bool Enabled { get => _enabled; set => _enabled = value; }
public bool Enabled { get; set; }
/// <summary>
/// The amount of time, in seconds, to remain connected after a close.
/// </summary>
public int LingerTime { get => _lingerTime; set => _lingerTime = value; }
}
}
public int LingerTime { get; set; }
}
}

Просмотреть файл

@ -6,13 +6,15 @@
namespace System.Net.Sockets
{
/// <summary>
/// Provides client connections for TCP network services.
/// </summary>
public class TcpClient : IDisposable
{
private Socket _client;
private NetworkStream _stream;
private bool disposedValue;
private AddressFamily _family = AddressFamily.InterNetwork;
bool _active;
private bool _disposed;
private readonly AddressFamily _family = AddressFamily.InterNetwork;
private bool _active;
/// <summary>
/// Initializes a new instance of the TcpClient class.
@ -29,7 +31,7 @@ namespace System.Net.Sockets
{
_family = localEP.AddressFamily;
initialize();
_client.Bind(localEP);
Client.Bind(localEP);
}
/// <summary>
@ -54,10 +56,10 @@ namespace System.Net.Sockets
{
Connect(hostname, port);
}
catch (Exception ex)
catch (Exception)
{
_client?.Close();
throw ex;
Client?.Close();
throw;
}
}
@ -67,18 +69,14 @@ namespace System.Net.Sockets
/// <param name="acceptedSocket"></param>
internal TcpClient(Socket acceptedSocket)
{
_client = acceptedSocket;
Client = acceptedSocket;
_active = true;
}
/// <summary>
/// Gets or sets the underlying Socket.
/// </summary>
public Socket Client
{
get => _client;
set => _client = value;
}
public Socket Client { get; set; }
/// <summary>
/// Returns the NetworkStream used to send and receive data to remote host.
@ -86,15 +84,11 @@ namespace System.Net.Sockets
/// <returns>The underlying NetworkStream.</returns>
public NetworkStream GetStream()
{
//if (!_client.Connected)
// {
// throw new InvalidOperationException("Not connected");
// }
if (_stream == null)
{
_stream = new NetworkStream(Client, true);
}
return _stream;
}
@ -102,20 +96,30 @@ namespace System.Net.Sockets
/// Gets the amount of data that has been received from the network
/// and is available to be read.
/// </summary>
public int Available { get => _client.Available; }
public int Available { get => Client.Available; }
private byte[] MilliSecsToTimeval(int millSecs)
{
byte[] timeval = new byte[8];
int secs = millSecs / 1000;
int usecs = (millSecs % 1000) * 1000;
/// <summary>
/// Return connection status of underlying socket.
/// </summary>
public bool Connected
{
get
{
// We should be returning the _client.Connected state but that's not available
// so for the moment just return active state
return _active;
}
byte[] bsecs = BitConverter.GetBytes(secs);
byte[] busecs = BitConverter.GetBytes(usecs);
Array.Copy(bsecs, timeval, 4);
Array.Copy(busecs, 0, timeval, 4, 4);
return timeval;
}
private int TimevalToMilliSecs(byte[] timeval)
{
// Bytes 0 - 3 secs
// Bytes 4 - 7 usecs
int secs = BitConverter.ToInt32(timeval, 0);
int usecs = BitConverter.ToInt32(timeval, 4);
return (secs * 1000) + (usecs / 1000);
}
/// <summary>
@ -125,13 +129,20 @@ namespace System.Net.Sockets
{
get
{
return (int)Client.GetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReceiveTimeout);
byte[] timeval = new byte[8];
Client.GetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReceiveTimeout, timeval);
return TimevalToMilliSecs(timeval);
}
set
{
byte[] timeval = MilliSecsToTimeval(value);
Client.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReceiveTimeout, value);
SocketOptionName.ReceiveTimeout, timeval);
}
}
@ -142,14 +153,20 @@ namespace System.Net.Sockets
{
get
{
return (int)Client.GetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.SendTimeout);
byte[] timeval = new byte[8];
Client.GetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.SendTimeout, timeval);
return TimevalToMilliSecs(timeval);
}
set
{
byte[] timeval = MilliSecsToTimeval(value);
Client.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.SendTimeout, value);
SocketOptionName.SendTimeout, timeval);
}
}
@ -161,8 +178,9 @@ namespace System.Net.Sockets
get
{
int optionValue = (int)Client.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger);
return (optionValue < 0)? new LingerOption(false, 0) : new LingerOption(true, optionValue);
return (optionValue < 0) ? new LingerOption(false, 0) : new LingerOption(true, optionValue);
}
set
{
int optionValue = value.Enabled ? value.LingerTime : -1;
@ -171,15 +189,17 @@ namespace System.Net.Sockets
}
/// <summary>
/// Enables or disables delay when send or receive buffers are full.
/// Enables or disables delay when send or receive buffers are not full. (Nagle)
/// True if delay is disabled.
/// </summary>
public bool NoDelay
{
get
{
return (int)Client.GetSocketOption(SocketOptionLevel.Tcp,
SocketOptionName.NoDelay) != 0 ? true : false;
SocketOptionName.NoDelay) != 0;
}
set
{
Client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, value ? 1 : 0);
@ -193,7 +213,7 @@ namespace System.Net.Sockets
/// <param name="remoteEP">The IPEndPoint to which you intend to connect.</param>
public void Connect(IPEndPoint remoteEP)
{
_client.Connect(remoteEP);
Client.Connect(remoteEP);
_active = true;
}
@ -215,7 +235,24 @@ namespace System.Net.Sockets
/// <param name="port">The port number to which you intend to connect.</param>
public void Connect(IPAddress[] address, int port)
{
Connect(new IPEndPoint(address[0], port));
foreach (IPAddress ipadr in address)
{
try
{
Connect(new IPEndPoint(ipadr, port));
break;
}
catch (Exception)
{
// Ignore exception as we will throw NotConnected exception
// if not connected, _active not set.
}
}
if (!_active)
{
throw new SocketException(SocketError.NotConnected);
}
}
/// <summary>
@ -238,7 +275,7 @@ namespace System.Net.Sockets
try
{
// Via host name, port constructor ?
if (_client == null)
if (Client == null)
{
ipv4Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
ipv6Socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
@ -248,12 +285,12 @@ namespace System.Net.Sockets
{
try
{
if (_client == null)
if (Client == null)
{
if (address.AddressFamily == AddressFamily.InterNetwork && ipv4Socket != null)
{
ipv4Socket.Connect(new IPEndPoint(address, port));
_client = ipv4Socket;
Client = ipv4Socket;
if (ipv6Socket != null)
{
ipv6Socket.Close();
@ -262,7 +299,7 @@ namespace System.Net.Sockets
else if (ipv6Socket != null)
{
ipv6Socket.Connect(new IPEndPoint(address, port));
_client = ipv4Socket;
Client = ipv4Socket;
if (ipv4Socket != null)
{
ipv4Socket.Close();
@ -285,6 +322,7 @@ namespace System.Net.Sockets
{
throw;
}
lastex = ex;
}
} // for each address
@ -295,6 +333,7 @@ namespace System.Net.Sockets
{
throw;
}
lastex = ex;
}
finally
@ -311,8 +350,12 @@ namespace System.Net.Sockets
{
ipv4Socket.Close();
}
}
}
}
if (!_active)
{
// Throw exception if connect failed
if (lastex != null)
{
@ -336,22 +379,22 @@ namespace System.Net.Sockets
private void initialize()
{
_client = new Socket(_family, SocketType.Stream, ProtocolType.Tcp);
Client = new Socket(_family, SocketType.Stream, ProtocolType.Tcp);
_active = false;
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
if (!_disposed)
{
if (disposing)
{
_stream?.Dispose();
_client?.Close();
_client = null;
Client?.Close();
Client = null;
}
disposedValue = true;
_disposed = true;
}
}

Просмотреть файл

@ -6,94 +6,103 @@
namespace System.Net.Sockets
{
public class TcpListener
{
EndPoint _localEndPoint;
Socket _listenSocket;
bool _active = false;
/// <summary>
/// Initializes a new instance of the TcpListener class that listens for incoming connection attempts on the specified local IP address and port number.
/// </summary>
/// <param name="localaddr">An IPAddress that represents the local IP address.</param>
/// <param name="port">The port on which to listen for incoming connection attempts.</param>
public TcpListener(IPAddress localaddr, int port) : this(new IPEndPoint(localaddr, port))
{
}
/// <summary>
/// Initializes a new instance of the TcpListener class that listens for incoming connection
/// attempts with the specified endpoint.
/// </summary>
/// <param name="localEP">An IPEndPoint that represents the local endpoint to which to bind the listener Socket.</param>
public TcpListener(IPEndPoint localEP)
/// <summary>
/// Listens for connections from TCP network clients.
/// </summary>
public class TcpListener
{
/// <summary>
/// Initializes a new instance of the TcpListener class that listens for incoming connection attempts on the specified local IP address and port number.
/// </summary>
/// <param name="localaddr">An IPAddress that represents the local IP address.</param>
/// <param name="port">The port on which to listen for incoming connection attempts.</param>
public TcpListener(IPAddress localaddr, int port) : this(new IPEndPoint(localaddr, port))
{
_localEndPoint = localEP;
_listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IPv4);
}
}
/// <summary>
/// Gets the underlying EndPoint of the current TcpListener.
/// </summary>
public EndPoint LocalEndpoint { get => _localEndPoint; }
/// <summary>
/// Initializes a new instance of the TcpListener class that listens for incoming connection
/// attempts with the specified endpoint.
/// </summary>
/// <param name="localEP">An IPEndPoint that represents the local endpoint to which to bind the listener Socket.</param>
public TcpListener(IPEndPoint localEP)
{
LocalEndpoint = localEP;
Server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IPv4);
}
/// <summary>
/// Gets the underlying network Socket.
/// </summary>
public Socket Server { get => _listenSocket; }
/// <summary>
/// Gets the underlying EndPoint of the current TcpListener.
/// </summary>
public EndPoint LocalEndpoint { get; }
/// <summary>
/// Gets a value that indicates whether TcpListener is actively listening
/// for client connections.
/// </summary>
protected bool Active { get => _active; }
/// <summary>
/// Gets the underlying network Socket.
/// </summary>
public Socket Server { get; private set; }
/// <summary>
/// Starts listening for incoming connection requests with a maximum number of pending connection.
/// </summary>
/// <param name="backlog">The maximum length of the pending connections queue.</param>
public void Start(int backlog)
{
if (_listenSocket == null)
/// <summary>
/// Gets a value that indicates whether TcpListener is actively listening
/// for client connections.
/// </summary>
protected bool Active { get; private set; }
/// <summary>
/// Starts listening for incoming connection requests with a maximum number of pending connection.
/// </summary>
/// <param name="backlog">The maximum length of the pending connections queue.</param>
public void Start(int backlog)
{
if (Active)
{
_listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IPv4);
}
throw new InvalidOperationException();
}
_listenSocket.Bind(_localEndPoint);
if (Server == null)
{
Server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IPv4);
}
_listenSocket.Listen(backlog);
Server.Bind(LocalEndpoint);
_active = true;
}
Server.Listen(backlog);
/// <summary>
/// Closes the listener.
/// </summary>
public void Stop()
Active = true;
}
/// <summary>
/// Closes the listener.
/// </summary>
public void Stop()
{
_listenSocket.Close();
_listenSocket = null;
_active = false;
}
if (Active)
{
throw new InvalidOperationException();
}
/// <summary>
/// Accepts a pending connection request.
/// </summary>
/// <returns>A TcpClient used to send and receive data.</returns>
public TcpClient AcceptTcpClient()
{
TcpClient client = new TcpClient(_listenSocket.Accept());
Server.Close();
Server = null;
Active = false;
}
return client;
}
/// <summary>
/// Accepts a pending connection request.
/// </summary>
/// <returns>A Socket used to send and receive data.</returns>
public Socket AcceptSocket()
/// <summary>
/// Accepts a pending connection request.
/// </summary>
/// <returns>A TcpClient used to send and receive data.</returns>
public TcpClient AcceptTcpClient()
{
return _listenSocket.Accept();
}
}
TcpClient client = new TcpClient(Server.Accept());
return client;
}
/// <summary>
/// Accepts a pending connection request.
/// </summary>
/// <returns>A Socket used to send and receive data.</returns>
public Socket AcceptSocket()
{
return Server.Accept();
}
}
}

Двоичные данные
nanoframework.System.Net.Sockets.TcpClient/key.snk Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -16,6 +16,15 @@
<AssemblyName>nanoframework.System.Net.Sockets.TcpClient</AssemblyName>
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup>
<DelaySign>false</DelaySign>
</PropertyGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
@ -25,27 +34,32 @@
</ItemGroup>
<ItemGroup>
<Reference Include="mscorlib, Version=1.12.0.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\packages\nanoFramework.CoreLibrary.1.12.0-preview.5\lib\mscorlib.dll</HintPath>
<HintPath>..\packages\nanoFramework.CoreLibrary.1.12.0-preview.9\lib\mscorlib.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="nanoFramework.Runtime.Events, Version=1.10.0.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\packages\nanoFramework.Runtime.Events.1.10.0-preview.6\lib\nanoFramework.Runtime.Events.dll</HintPath>
<HintPath>..\packages\nanoFramework.Runtime.Events.1.10.0-preview.8\lib\nanoFramework.Runtime.Events.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="nanoFramework.System.Text, Version=1.1.3.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\packages\nanoFramework.System.Text.1.1.3-preview.13\lib\nanoFramework.System.Text.dll</HintPath>
<HintPath>..\packages\nanoFramework.System.Text.1.1.3-preview.15\lib\nanoFramework.System.Text.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="System.IO.Streams, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\packages\nanoFramework.System.IO.Streams.1.0.0-preview.12\lib\System.IO.Streams.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="System.Net, Version=1.8.0.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\packages\nanoFramework.System.Net.1.8.0-preview.26\lib\System.Net.dll</HintPath>
<HintPath>..\packages\nanoFramework.System.Net.1.8.0-preview.29\lib\System.Net.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="System.Threading, Version=1.0.4.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\packages\nanoFramework.System.Threading.1.0.4-preview.14\lib\System.Threading.dll</HintPath>
<HintPath>..\packages\nanoFramework.System.Threading.1.0.4-preview.16\lib\System.Threading.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
@ -59,4 +73,11 @@
<ProjectConfigurationsDeclaredAsItems />
</ProjectCapabilities>
</ProjectExtensions>
<Import Project="..\packages\Nerdbank.GitVersioning.3.4.194\build\Nerdbank.GitVersioning.targets" Condition="Exists('..\packages\Nerdbank.GitVersioning.3.4.194\build\Nerdbank.GitVersioning.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Nerdbank.GitVersioning.3.4.194\build\Nerdbank.GitVersioning.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Nerdbank.GitVersioning.3.4.194\build\Nerdbank.GitVersioning.targets'))" />
</Target>
</Project>

Просмотреть файл

@ -1,8 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="nanoFramework.CoreLibrary" version="1.12.0-preview.5" targetFramework="netnanoframework10" />
<package id="nanoFramework.Runtime.Events" version="1.10.0-preview.6" targetFramework="netnanoframework10" />
<package id="nanoFramework.System.Net" version="1.8.0-preview.26" targetFramework="netnanoframework10" />
<package id="nanoFramework.System.Text" version="1.1.3-preview.13" targetFramework="netnanoframework10" />
<package id="nanoFramework.System.Threading" version="1.0.4-preview.14" targetFramework="netnanoframework10" />
<package id="nanoFramework.CoreLibrary" version="1.12.0-preview.9" targetFramework="netnanoframework10" />
<package id="nanoFramework.Runtime.Events" version="1.10.0-preview.8" targetFramework="netnanoframework10" />
<package id="nanoFramework.System.IO.Streams" version="1.0.0-preview.12" targetFramework="netnanoframework10" />
<package id="nanoFramework.System.Net" version="1.8.0-preview.29" targetFramework="netnanoframework10" />
<package id="nanoFramework.System.Text" version="1.1.3-preview.15" targetFramework="netnanoframework10" />
<package id="nanoFramework.System.Threading" version="1.0.4-preview.16" targetFramework="netnanoframework10" />
<package id="Nerdbank.GitVersioning" version="3.4.194" targetFramework="netnanoframework10" developmentDependency="true" />
</packages>

23
version.json Normal file
Просмотреть файл

@ -0,0 +1,23 @@
{
"$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
"version": "1.0.0-preview.{height}",
"assemblyVersion": {
"precision": "revision"
},
"semVer1NumericIdentifierPadding": 3,
"nuGetPackageVersion": {
"semVer": 2.0
},
"publicReleaseRefSpec": [
"^refs/heads/main$",
"^refs/heads/v\\d+(?:\\.\\d+)?$"
],
"cloudBuild": {
"setAllVariables": true
},
"release": {
"branchName": "release-v{version}",
"versionIncrement": "build",
"firstUnstableTag": "preview"
}
}