Add very simple easy networking basic, not much, simple

This commit is contained in:
Sofia 2020-08-02 03:50:01 +03:00
parent db267bb972
commit 2939eecc8b
15 changed files with 332 additions and 0 deletions

8
Assets/Scripts.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 06f737a2dd3e1214a9e33c689e945955
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Scripts/Net.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5b2b07bcc084a8f449d46fad84fb9149
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,30 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using NeonTea.Quakeball.Net.Endpoint;
namespace NeonTea.Quakeball.Net {
public class CanvasInput : MonoBehaviour {
public Button Host;
public Button Join;
public InputField HostAddr;
public InputField Port;
void Start() {
Host.onClick.AddListener(() => {
//Destroy(Join.gameObject);
//Host.interactable = false;
Network.Singleton.Start(new Server(), "0.0.0.0", 8080);
});
Join.onClick.AddListener(() => {
//Destroy(Host.gameObject);
//Join.interactable = false;
Network.Singleton.Start(new Client(), "127.0.0.1", 8080);
});
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5c88f7b0d79ee6d40adc7ee64150d47e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,17 @@
using System.Collections;
using System.Collections.Generic;
using System.Net;
namespace NeonTea.Quakeball.Net {
public class Connection {
public IPEndPoint Endpoint;
public uint uuid;
public bool ShouldExist = true;
public Connection(IPEndPoint endpoint, uint uuid) {
this.Endpoint = endpoint;
this.uuid = uuid;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bee661c56fae81b4885405c7da9fbb08
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9d5b2ed44f40cc940bae2d8e4c868bf4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,46 @@
using UnityEngine;
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace NeonTea.Quakeball.Net.Endpoint {
public class Client : AbstractEndpoint {
public override UdpClient UdpClient {
get { return InnerClient; }
}
private Connection Connection;
private UdpClient InnerClient;
public override void Start(string host, int port) {
InnerClient = new UdpClient(0);
try {
Connection = new Connection(new IPEndPoint(FindAddress(host), port), 0);
} catch (Exception e) {
Debug.Log($"Failed to create initial connection: {e.ToString()}");
Network.Singleton.Stop();
}
StartListen(Connection);
SendBytes(Encoding.UTF8.GetBytes("Hello! This is testing."));
Debug.Log($"Client started at {host}:{port}!");
}
public void OnStop() {
Connection.ShouldExist = false;
}
public override void ConnectionClosed(Connection conn, ClosingReason reason) {
if (Connection == conn) { // Make sure the closed connection is this one
Debug.Log($"Closing client. Connection was closed: {reason.Description}");
Network.Singleton.Stop();
}
}
private void SendBytes(Byte[] bytes) {
UdpClient.Send(bytes, bytes.Length, Connection.Endpoint);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ffeef21f11f5f864f9213c2822a05d38
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,80 @@
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
namespace NeonTea.Quakeball.Net.Endpoint {
public abstract class AbstractEndpoint {
private Dictionary<uint, Thread> ListenThreads = new Dictionary<uint, Thread>();
public abstract void Start(string host, int port);
public abstract UdpClient UdpClient { get; }
public virtual void ConnectionClosed(Connection conn, ClosingReason reason) {
}
public void Stop() {
UdpClient.Close();
foreach (Thread thread in ListenThreads.Values) {
thread.Abort();
}
}
protected IPAddress FindAddress(string host) {
IPAddress addr;
try {
addr = Dns.GetHostAddresses(host)[0];
} catch (ArgumentException) {
addr = IPAddress.Parse(host);
}
return addr;
}
protected bool StartListen(Connection connection) {
if (ListenThreads.ContainsKey(connection.uuid)) {
return false;
}
Thread t = new Thread(ListenThread);
t.Start(connection);
ListenThreads.Add(connection.uuid, t);
return true;
}
private void ListenThread(object obj) {
Connection listened;
try {
listened = (Connection)obj;
} catch (InvalidCastException) {
Debug.Log($"Can not cast {obj} to a Connection");
return;
}
while (listened.ShouldExist) {
try {
Byte[] Received = UdpClient.Receive(ref listened.Endpoint);
Debug.Log(Encoding.UTF8.GetString(Received));
} catch (Exception e) {
Debug.Log($"Error listening to connection, closing connection: {e.ToString()}");
listened.ShouldExist = false;
ConnectionClosed(listened, new ClosingReason(Reason.LISTENING_ERROR, e.ToString()));
}
}
}
}
}
public struct ClosingReason {
public Reason Reason;
public string Description;
public ClosingReason(Reason reason, string description) {
Reason = reason;
Description = description;
}
}
public enum Reason {
LISTENING_ERROR
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: de661f9bd7cfa694db4111a798643dd3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,43 @@
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Net;
using System.Net.Sockets;
namespace NeonTea.Quakeball.Net.Endpoint {
public class Server : AbstractEndpoint {
public override UdpClient UdpClient {
get { return InnerClient; }
}
private static uint ConnectionUUIDCounter;
private Dictionary<uint, Connection> Connections = new Dictionary<uint, Connection>();
private UdpClient InnerClient;
public override void Start(string host, int port) {
InnerClient = new UdpClient(port);
Connection conn;
try {
conn = AddConnection(new IPEndPoint(FindAddress(host), port), uint.MaxValue);
} catch (Exception e) {
Debug.Log($"Failed to create initial connection: {e.ToString()}");
Network.Singleton.Stop();
return;
}
StartListen(conn);
Debug.Log($"Server started at {host}:{port}!");
}
private Connection AddConnection(IPEndPoint endpoint, uint uuid = 0) {
if (uuid == 0) {
uuid = ConnectionUUIDCounter++;
}
Connection conn = new Connection(endpoint, uuid);
Connections.Add(uuid, conn);
return conn;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 08642b59bb65292409a46c688efbf134
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,26 @@
using UnityEngine;
using NeonTea.Quakeball.Net.Endpoint;
using System.Threading;
namespace NeonTea.Quakeball.Net {
public class Network {
public static Network Singleton = new Network();
private AbstractEndpoint Endpoint;
public void Start(AbstractEndpoint endpoint, string host, int port) {
if (Endpoint != null) {
Debug.Log("Can not start multiple endpoints at once! Use Server if multiple connections are required.");
return;
}
Endpoint = endpoint;
Endpoint.Start(host, port);
}
public void Stop() {
Endpoint.Stop();
Endpoint = null;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d8773e20fdc6d1842848081eaf595ad5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: