Skip to content

Instantly share code, notes, and snippets.

@brianmed
Last active December 2, 2022 04:54
Show Gist options
  • Save brianmed/d9f0f440abe334c09abd578643327457 to your computer and use it in GitHub Desktop.
Save brianmed/d9f0f440abe334c09abd578643327457 to your computer and use it in GitHub Desktop.
Separate sending and receiving sockets.. hopefully
<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>
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