library only

This commit is contained in:
waltem01 2022-06-27 08:44:26 +02:00
parent cba4136151
commit 5009197a70
7 changed files with 144 additions and 282 deletions

6
.gitignore vendored
View File

@ -1,4 +1,8 @@
client/bin/*
client/obj/*
server/bin/*
server/obj/*
server/obj/*
SocketLib/obj/*
SocketLib/bin/*

130
SocketLib/SocketLib.cs Normal file
View File

@ -0,0 +1,130 @@
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections;
namespace SocketLib;
public static class Server {
public static Socket self;
private static byte[] buffer;
private static string ipAddress;
private static int listeners = 0;
public static Action<Socket> disconnectMethod;
public static List<MessageEvent> messageEvents;
public static void Initialize() {
// Initialize global variables
buffer = new byte[1024];
messageEvents = new List<MessageEvent>();
disconnectMethod = new Action<Socket>((other)=>{});
// Get computers' ipv4 address
ipAddress = "127.0.0.1";
try {
string hostName = Dns.GetHostName();
IPHostEntry entryList = Dns.GetHostEntry(hostName);
IPAddress ipv4Entry = entryList.AddressList[0];
ipAddress = ipv4Entry.ToString();
} catch (Exception) {}
}
public static void Start() {
// Create a new socket server and listen for connections
self = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
self.Bind(new IPEndPoint(IPAddress.Parse(ipAddress), 3000));
self.Listen(10);
// Accept any client asynchronously
while (true) {
if (listeners < 10) {
self.BeginAccept(new AsyncCallback(AcceptCallback), self);
listeners++;
} else {
// If there are already 10 async callbacks running, then sleep
Thread.Sleep(500);
}
}
}
// End off the message send-callback
private static void SendCallback(IAsyncResult AR) {
Socket other = AR.AsyncState as Socket;
other.EndSend(AR);
}
// End off the message receive-callback
private static void ReceiveCallback(IAsyncResult AR) {
Socket other = AR.AsyncState as Socket;
try {
// Handle any received bytes
int received = other.EndReceive(AR);
if (received <= 0)
throw new Exception();
byte[] data = new byte[received];
Array.Copy(buffer, data, received);
// Convert bytes to string
string message = Encoding.UTF8.GetString(data);
// Handle received message
handleMessage(message, other);
// Begin listening for more messages
other.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), other);
} catch (Exception) {
// Potentially detected Disconnect
if (other.Connected) {
// Close client connection
disconnectMethod.Invoke(other);
other.Close();
}
}
}
// End off the connection accept-callback
private static void AcceptCallback(IAsyncResult AR) {
Socket own = AR.AsyncState as Socket;
Socket other = own.EndAccept(AR);
listeners--;
other.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), other);
}
// Handle sending messages
public static void Send(Socket other, string text) {
byte[] data = Encoding.UTF8.GetBytes(text);
other.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback(SendCallback), other);
}
// Handle any incomming messages from given client
private static void handleMessage(string message, Socket other) {
Console.WriteLine($"Recieved Message: {message}");
string[] splits = message.Split(' ');
string eventName = splits[0];
string rest = "";
for (int i = 1; i < splits.Length; i++)
rest += splits[i] + ((i < splits.Length-1) ? " " : "");
// Console.WriteLine($"Event: {eventName}; Params: {rest}; Methods: {messageEvents.Count};");
foreach (MessageEvent mE in messageEvents) {
if (mE.name == eventName) {
if (rest == "")
mE.method.DynamicInvoke(other);
else
mE.method.DynamicInvoke(other, rest);
// Console.WriteLine("Method was Invoked.");
}
}
}
}
// Custom Class to store event methods by name
public class MessageEvent {
public string name;
public MulticastDelegate method;
public MessageEvent(string _name, MulticastDelegate _method) {
name = _name;
method = _method;
}
}

View File

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -1,80 +0,0 @@
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace SocketTestClient {
class Client {
static byte[] buffer;
static void Main(string[] args) {
// Initialize global variables
buffer = new byte[1024];
// Get server ipv4 address
string ipAddress = "127.0.0.1";
int port = 3000;
Console.WriteLine("Enter the Server IP and Port");
Console.Write("(Format: IPv4:Port; Default: EMPTY): ");
string input = Console.ReadLine();
if (input != "") {
string[] splits = input.Split(':');
if (splits.Length == 2) {
ipAddress = splits[0];
port = int.Parse(splits[1]);
}
}
// Connect to SocketServer on 'localhost:3000' and send a message
Socket client = null;
try {
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
client.Connect(new IPEndPoint(IPAddress.Parse(ipAddress), port));
} catch (Exception) {
Console.WriteLine("Could not connect to server.");
Environment.Exit(0);
}
// Receive and display messages in new thread
client.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), client);
while (true) {
Console.Write("Enter a message or comand: ");
string message = Console.ReadLine();
if (message.ToLower() == "exit")
break;
else if (message.ToLower() == "clear") {
Console.Clear();
continue;
}
byte[] data = Encoding.UTF8.GetBytes(message);
client.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback(SendCallback), client);
Console.WriteLine($"Sent message '{message}' to server.");
}
client.Close();
}
static void SendCallback(IAsyncResult AR) {
Socket self = AR.AsyncState as Socket;
self.EndSend(AR);
}
static void ReceiveCallback(IAsyncResult AR) {
Socket self = AR.AsyncState as Socket;
try {
int received = self.EndReceive(AR);
if (received <= 0)
throw new Exception();
byte[] data = new byte[received];
Array.Copy(buffer, data, received);
string message = Encoding.ASCII.GetString(data);
Console.WriteLine($"Received message: '{message}' from server.");
self.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), self);
} catch (Exception) {
Console.WriteLine("Closing program due to error or disconnect . . . ");
self.Close();
}
}
}
}

View File

@ -1,8 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
</Project>

View File

@ -1,185 +0,0 @@
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections.Generic;
namespace SocketTestServer {
class Server {
static Socket server;
static List<Lobby> lobbies;
static byte[] buffer;
static int listeners = 0;
static void Main(string[] args) {
// Initialize global bariables
buffer = new byte[1024];
lobbies = new List<Lobby>();
// Get computers' ipv4 address
string ipAddress = "127.0.0.1";
try {
string hostName = Dns.GetHostName();
IPHostEntry entryList = Dns.GetHostEntry(hostName);
IPAddress ipv4Entry = entryList.AddressList[0];
ipAddress = ipv4Entry.ToString();
} catch (Exception) {}
// Create a new socket server and listen for connections
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(new IPEndPoint(IPAddress.Parse(ipAddress), 3000));
server.Listen(10);
// Accept any client asynchronously
while (true) {
if (listeners < 10) {
server.BeginAccept(new AsyncCallback(AcceptCallback), server);
listeners++;
} else {
// If there are already 10 async callbacks running, then sleep
Thread.Sleep(500);
}
}
}
// End off the message send-callback
static void SendCallback(IAsyncResult AR) {
Socket self = AR.AsyncState as Socket;
self.EndSend(AR);
}
// End off the message receive-callback
static void ReceiveCallback(IAsyncResult AR) {
Socket self = AR.AsyncState as Socket;
try {
// Handle any received bytes
int received = self.EndReceive(AR);
if (received <= 0)
throw new Exception();
byte[] data = new byte[received];
Array.Copy(buffer, data, received);
// Convert bytes to string
string message = Encoding.UTF8.GetString(data);
// Handle received message
handleMessage(message, self);
// Begin listening for more messages
self.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), self);
} catch (Exception) {
// Potentially detected Disconnect
if (self.Connected) {
// Remove client from lobby, and lobby from list
foreach (Lobby l in lobbies) {
if (l.users.Contains(self))
l.users.Remove(self);
if (l.users.Count == 0) {
lobbies.Remove(l);
Console.WriteLine("Closed Lobby.");
}
}
// Close client connection
self.Close();
}
}
}
// End off the connection accept-callback
static void AcceptCallback(IAsyncResult AR) {
Socket self = AR.AsyncState as Socket;
Socket other = self.EndAccept(AR);
listeners--;
other.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), other);
}
// Handle any incomming messages from given client
static void handleMessage(string message, Socket other) {
// Keep lowercase copy
string copy = message.ToLower();
string response = "";
// Create new with random code lobby and add client to it
if (copy == "new lobby") {
Random rng = new Random();
string lobbyCode = "";
while (lobbyCode.Length < 6)
lobbyCode += (char)rng.Next(33, 127);
lobbies.Add(new Lobby(other, lobbyCode));
response = $"Created {lobbyCode}";
Console.WriteLine($"Created Lobby '{lobbyCode}'");
// Give Lobby-Count feedback
} else if (copy == "lobby count") {
response = $"Count {lobbies.Count}";
Console.WriteLine($"Replied with count '{lobbies.Count}'.");
// Check for any disconnected Clients, remove them from lobbies and lobby from list
} else if (copy == "check connections") {
foreach (Lobby l in lobbies) {
Console.WriteLine($"Lobby: {l.code}");
foreach (Socket s in l.users)
try {
if (!s.Connected) {
s.Close();
l.users.Remove(s);
Console.WriteLine("User Disconnected.");
}
} catch (Exception) {}
if (l.users.Count == 0) {
lobbies.Remove(l);
Console.WriteLine("Closed Lobby.");
}
}
response = "Verified all Connections.";
// Other possible message combinations
} else {
string[] splits = copy.Split(' ');
// Check if user is in a lobby or add them to wished lobby
if (splits.Length >= 3 && splits[0]+' '+splits[1] == "join lobby") {
string lobbyCode = splits[2];
foreach (Lobby l in lobbies) {
if (l.users.Contains(other)) {
response = $"Already in a Lobby";
break;
} else if (l.code == lobbyCode) {
l.users.Add(other);
response = $"Joined {lobbyCode}";
break;
}
}
// Handle feedback for Lobbies
if (response.Split(' ')[0] == "Joined")
Console.WriteLine($"Added User to Lobby '{lobbyCode}'.");
else {
response = "No Lobby with this Code available.";
Console.WriteLine($"Could not add user to Lobby '{lobbyCode}'.");
}
// Ignore any remaining possible messages
} else
Console.WriteLine($"Ignored message '{message}'.");
}
// Respond to client if an action was executed successfully.
if (response != "") {
byte[] data = Encoding.UTF8.GetBytes(response);
other.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback(SendCallback), other);
}
}
// Custom Lobby class
class Lobby {
// Keep track of own lobby code and list of users
public List<Socket> users;
public string code;
// Initialize Lobby with current user in list and given lobby code
public Lobby(Socket other, string lobbyCode) {
users = new List<Socket>();
users.Add(other);
code = lobbyCode;
}
}
}
}

View File

@ -1,8 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
</Project>