mirror of
https://gitlab1.ptb.de/waltem01/csharpsocketserver
synced 2024-02-04 23:19:43 +00:00
initial commit
This commit is contained in:
commit
c8d5d0d77c
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
client/bin/*
|
||||
client/obj/*
|
||||
server/bin/*
|
||||
server/obj/*
|
80
client/Program.cs
Normal file
80
client/Program.cs
Normal file
|
@ -0,0 +1,80 @@
|
|||
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; Press ENTER for default): ");
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
8
client/client.csproj
Normal file
8
client/client.csproj
Normal file
|
@ -0,0 +1,8 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
185
server/Program.cs
Normal file
185
server/Program.cs
Normal file
|
@ -0,0 +1,185 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
8
server/SocketTest.csproj
Normal file
8
server/SocketTest.csproj
Normal file
|
@ -0,0 +1,8 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
Loading…
Reference in New Issue
Block a user