Last active
December 2, 2022 04:54
-
-
Save brianmed/d9f0f440abe334c09abd578643327457 to your computer and use it in GitHub Desktop.
Separate sending and receiving sockets.. hopefully
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Project Sdk="Microsoft.NET.Sdk"> | |
<PropertyGroup> | |
<OutputType>Exe</OutputType> | |
<TargetFramework>net6.0</TargetFramework> | |
<ImplicitUsings>enable</ImplicitUsings> | |
<Nullable>enable</Nullable> | |
<_EnableMacOSCodeSign>false</_EnableMacOSCodeSign> | |
</PropertyGroup> | |
<ItemGroup> | |
<PackageReference Include="System.CommandLine.DragonFruit" Version="0.4.0-alpha.22272.1" /> | |
<PackageReference Include="System.Text.Json" Version="7.0.0" /> | |
</ItemGroup> | |
</Project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Concurrent; | |
using System.Linq; | |
using System.Net; | |
using System.Net.Sockets; | |
using System.Text; | |
using System.Text.Json; | |
namespace MultipleSockets; | |
class Message | |
{ | |
public int Pid { get; set; } | |
public int ManagedThreadId { get; set; } | |
public string Body { get; set; } | |
} | |
// $ ./MultipleSockets --remote-host localhost --recv-port 8000 --send-port 8001 | |
// $ ./MultipleSockets --remote-host localhost --recv-port 8001 --send-port 8000 --body joy | |
class Program | |
{ | |
static BlockingCollection<Message> bc = new(); | |
static async Task Main(string remoteHost, int sendPort, int recvPort, string body) | |
{ | |
Task sendAsync = SendAsync(remoteHost, sendPort); | |
Task receiveAsync = ReceiveAsync(recvPort); | |
if (body is not null) | |
{ | |
bc.Add(new() | |
{ | |
Body = body, | |
ManagedThreadId = Thread.CurrentThread.ManagedThreadId, | |
Pid = System.Diagnostics.Process.GetCurrentProcess().Id, | |
}); | |
} | |
await Task.WhenAll(new[] { sendAsync, receiveAsync }); | |
} | |
static async Task SendAsync(string remoteHost, int remotePort) | |
{ | |
using Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp); | |
foreach (int _ in Enumerable.Range(0, 30)) | |
{ | |
try | |
{ | |
await socket.ConnectAsync(remoteHost, remotePort); | |
break; | |
} | |
catch (Exception ex) | |
{ | |
await Console.Out.WriteLineAsync(ex.ToString()); | |
await Task.Delay(TimeSpan.FromSeconds(3)); | |
} | |
} | |
while (true) | |
{ | |
if (bc.TryTake(out Message joy)) | |
{ | |
byte[] requestBytes = Encoding.ASCII.GetBytes($"{JsonSerializer.Serialize(joy)}\n"); | |
int bytesSent = 0; | |
while (bytesSent < requestBytes.Length) | |
{ | |
bytesSent += await socket.SendAsync(requestBytes.AsMemory(bytesSent), SocketFlags.None); | |
} | |
} | |
// await Task.Delay(TimeSpan.FromSeconds(0.05)); | |
} | |
} | |
static async Task ReceiveAsync(int recvPort) | |
{ | |
Socket listeningSocket = new Socket(SocketType.Stream, ProtocolType.Tcp); | |
listeningSocket.Bind(new IPEndPoint(IPAddress.Any, recvPort)); | |
listeningSocket.Listen(1); | |
using (Socket acceptedSocket = await listeningSocket.AcceptAsync()) | |
{ | |
int bufferLength = 256; | |
List<char> overflow = new(); | |
while (true) | |
{ | |
int idx = 0; | |
int charCount = 0; | |
byte[] responseBytes = new byte[bufferLength]; | |
char[] responseChars = new char[bufferLength]; | |
if (overflow.Any()) | |
{ | |
await Console.Out.WriteLineAsync("Overflow Taken Care of"); | |
} | |
for (; idx < overflow.Count(); ++idx) | |
{ | |
responseChars[idx] = overflow[idx]; | |
++idx; | |
overflow.Clear(); | |
} | |
while (responseChars.Any(rc => rc.Equals('\n')) is false) | |
{ | |
ArraySegment<byte> joy = new ArraySegment<byte>(responseBytes, idx, bufferLength - idx); | |
int bytesReceived = await acceptedSocket.ReceiveAsync(joy, SocketFlags.None); | |
charCount += Encoding.ASCII.GetChars(responseBytes, 0, bytesReceived, responseChars, 0); | |
idx += bytesReceived; | |
} | |
try | |
{ | |
ArraySegment<char> joy = new ArraySegment<char>(responseChars, 0, charCount); | |
string[] pieces = new string(joy).Split("\n").ToArray(); | |
Message message = JsonSerializer.Deserialize<Message>(new string(pieces[0])); | |
await Console.Out.WriteLineAsync(new string(pieces[0])); | |
foreach (string over in pieces.Skip(1)) | |
{ | |
overflow.AddRange(over); | |
} | |
bc.Add(new() | |
{ | |
Body = message.Body, | |
ManagedThreadId = Thread.CurrentThread.ManagedThreadId, | |
Pid = System.Diagnostics.Process.GetCurrentProcess().Id, | |
}); | |
} | |
catch (Exception ex) | |
{ | |
await Console.Out.WriteLineAsync(ex.ToString()); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment