Trädvy Permalänk
Medlem
Plats
Datorn
Registrerad
Aug 2005

Hjälp med nätverks klass

Hej,
har suttit och pillat med en nätverksklass till ett framtida spel, har kollat en del på nätverkskod, men inte hittat någon bra färdig klass (enligt mig).
Så jag betämde mig för att skriva en egen och den fungerar nästan helt..
Koden ser för tillfället ut såhär (C#):

Server:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Net; using System.Net.Sockets; using System.Threading; namespace ServerNetworking { public class ServerNetworking { private IPEndPoint ip; private Socket socket; private Socket client; private IPEndPoint newclient; private NetworkStream netStream; private StreamReader netStreamReader; private StreamWriter netStreamWriter; private Thread netListen; private String data; private bool running; public bool isPackage; public ServerNetworking() { ip = new IPEndPoint(IPAddress.Any, 8000); netListen = new Thread(NetListener); running = true; isPackage = false; socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { socket.Bind(ip); } catch (SocketException e) { } socket.Listen(10); client = socket.Accept(); newclient = (IPEndPoint)client.RemoteEndPoint; netStream = new NetworkStream(client); netStreamReader = new StreamReader(netStream); netStreamWriter = new StreamWriter(netStream); } private void NetListener() { while (running) { data = netStreamReader.ReadLine(); isPackage = true; } } public void CloseConnection() { running = false; socket.Shutdown(SocketShutdown.Both); netStreamReader.Close(); netStreamWriter.Close(); netStream.Close(); client.Close(); socket.Close(); } public String GetPackage() { isPackage = false; return data; } public void SendPackage(String sendData) { netStreamWriter.WriteLine(sendData); netStreamWriter.Flush(); } } }

Client:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Net; using System.Net.Sockets; using System.Threading; namespace ClientNetworking { public class ClientNetworking { private IPAddress host; private IPEndPoint hostep; private Socket socket; private NetworkStream netStream; private StreamReader netStreamReader; private StreamWriter netStreamWriter; private Thread netListen; private String data; private bool running; public bool isPackage; public ClientNetworking() { host = IPAddress.Parse("127.0.0.1"); hostep = new IPEndPoint(host, 8000); socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); netListen = new Thread(NetListener); running = true; isPackage = false; try { socket.Connect(hostep); } catch (SocketException e) { } netStream = new NetworkStream(socket); netStreamReader = new StreamReader(netStream); netStreamWriter = new StreamWriter(netStream); netListen.Start(); } private void NetListener() { while (running) { data = netStreamReader.ReadLine(); isPackage = true; } } public void CloseConnection() { running = false; socket.Shutdown(SocketShutdown.Both); netStreamReader.Close(); netStreamWriter.Close(); netStream.Close(); socket.Close(); } public String GetPackage() { isPackage = false; return data; } public void SendPackage(String sendData) { netStreamWriter.WriteLine(sendData); netStreamWriter.Flush(); } } }

Just nu kan clienten koppla upp sig mot servern och man kan skicka data från servern till clienten, men inte från clienten till servern..

Kan någon hjälpa mig att få till det sista skulle jag vara tacksam.

Tack på förhand, Torxx.

Torxx

Trädvy Permalänk
Medlem
Plats
Göteborg
Registrerad
Nov 2007

Tycker att du skall fråga dig vad för slags kommunikation du vill ha innan du börjar skriva någon kod.
Typ:
Hur många Klienter är uppkopplade samtidigt ?
Är det 1 server ? (antar det)
Är det synkron kommunikation eller asynkron ?
Vad för typ av packet ska skickas till andra sidan ?
(Tror ju inte det kommer att vara ascii => tveksamt med readline)

Synkron kommunikation kan beskrivas som:
Du ställer en fråga och sedan väntar hela programmet tills dess att du får ett svar.. Tex ett schack spel

Asynkront Du ställer frågor eller skickar data, eventuellt kommer det in svars packet, men det behandlar du då (ifall det kommer något). Skulle tex kunna skicka ett serie nummer med varje "fråga" och svars packeten innehåller samma nummer som skickades vid frågan.

Trädvy Permalänk
Medlem
Plats
Uddevalla
Registrerad
Okt 2001

När koden går in i denna loopen i server delen

private void NetListener() { while (running) { data = netStreamReader.ReadLine(); isPackage = true; } }

Kan den komma ur då?
Hur kallar du på de olika funktionerna?

Macbook Air 13" (2012)

Trädvy Permalänk
Medlem
Plats
Datorn
Registrerad
Aug 2005

sag:
det kommer att vara ett slags RPG, så det kommer att vara flera clients uppkopplade till en server och kommunikationen kommer att vara asynkron.
Vilken typ av packet jag kommer skicka är jag inte helt säker på än, men jag tänkte skicka strängar med data för att slippa trasslet med längden på paketen som man har om man skickar byte för byte.

wisdom:
NetListner() är en egen tråd och netStreamReader.ReadLine() är en funktion som inte returnerar något förens det finns ett paket att hämta.
Funktionerna lägger jag i en dll fil och de anropas från huvudprogrammet.
Huvudprogrammet skapar ett nytt objekt av klassen och sedan behöver man bara anropa GetPackage() och SendPackage(String sendData) i programmet..
Mottagningen av trafik gör NetListner() automatiskt och när det finns ett packet att hämta (isPackage == true) anropas GetPackage().

Torxx

Trädvy Permalänk
Medlem
Plats
Göteborg
Registrerad
Nov 2007

Jag ogillar hela kod snurran du har skrivit i server delen(och klienten).
Jag har inte skrivit något liknande i C++ men har gjort det i C.

Beroende på hur spelet fungerar så behöver du köra på något annat sätt en med ReadLine.
Om readline fungerar som jag antar, så kommer den att blockera hela tråden tills dess att du skickar en newline.
DVS om man skickar något i stil med "aaaa" Utan någon CrLF eller newline saker på slutet.

ReadLine på det sättet gör att servern blir sårbar för attacker i den stilen.
( Vad händer om jag skickar in 2 Miljarder tecken "a" ? => Server krash ?)

Tycker att det är bättre att gå på nätverks protokollet på så låg nivå som möjligt.
Låt bli att wrappa upp allt i C++ klasser.

Visst kan du skriva (och bör) en C++ klass som hanterar alla nätverks grejer..
MEN hur skall du hantera servern när flera klienter kommer in ?
Trådar du eller skall du köra med någon Poll/ Select /( Finns säkert andra motsvarande funktioner på Microsoft ) ?

Trädvy Permalänk
Medlem
Plats
Datorn
Registrerad
Aug 2005

Vad jag förstår läser ReadLine in en String, String i c# fungerar lite annorlunda mot de i c eller c++, men jag tror att du kan ha rätt i att den kan vara väldig sårbar för attacker.. Jag bör nog använda mig av det mest basic sättet och skicka bytefält istället.

Vad gäller flera clienter så kom på att jag inte har något bra sätt med den koden jag har för tillfället och att jag inte vet vad Poll / Select är..
Men jag letade runt lite och hittade en halvfärdig nätverksklass som jag lade ner när jag trodde att StreamReader/StreamWriter var bättre..
Där använder jag listeningSocet.BeginAccept(new AsyncCallback(OnClientConnect), null); när jag börjar lyssna. Den startar en tråd som lyssnar efter data.
Det coola jag kom på var att istället för null kan man skicka med en Object som är unik för just den uppkopplingen. Kommer inte ihåg precis hur det fungerar, men jag tror att jag kan hålla koll på flera clients genom att ge dem olika Objects. (Någon som kan styrka detta). Isåfall löser jag problemet med flera clients. Men då vet jag inte hur jag får StreamReader/StreamWriter att fungera, men jag tror ändå att jag ska byta till bytefält.
Låter det som något att satsa på?

Tack för svaren, Torxx.

Torxx