mirror of
https://gitlab1.ptb.de/waltem01/csharpsocketserver
synced 2024-02-04 23:19:43 +00:00
library only
This commit is contained in:
parent
cba4136151
commit
5009197a70
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -1,4 +1,8 @@
|
|||
client/bin/*
|
||||
client/obj/*
|
||||
|
||||
server/bin/*
|
||||
server/obj/*
|
||||
server/obj/*
|
||||
|
||||
SocketLib/obj/*
|
||||
SocketLib/bin/*
|
130
SocketLib/SocketLib.cs
Normal file
130
SocketLib/SocketLib.cs
Normal 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;
|
||||
}
|
||||
}
|
9
SocketLib/SocketLib.csproj
Normal file
9
SocketLib/SocketLib.csproj
Normal file
|
@ -0,0 +1,9 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
Loading…
Reference in New Issue
Block a user