Laden...

NetworkStream dauerhaft auslesen

Erstellt von Odin008 vor 9 Jahren Letzter Beitrag vor 9 Jahren 3.174 Views
O
Odin008 Themenstarter:in
58 Beiträge seit 2013
vor 9 Jahren
NetworkStream dauerhaft auslesen

Moin,

Ich habe ein Problem was ich nicht so ganz verstehe
Es sieht folgendermaßen aus:

Server -> startet
Server -> startet ein Minecraft Server und fängt den output ab
Server -> sendet den abgefangenen output zu allen verbundenen Clients

Client -> Verbindet sich zum Server
Server -> Meldet Client Connected
Client -> Soll solange daten gesendet werden diese auslesen und anzeigen so das ich eine Kopie der Server Konsole habe. Klappt aber nicht ganz entweder kann ich nur 1x auslesen oder garnicht.

Server:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Diagnostics;
namespace MinecraftServerManager.TCPIP
{
    /*************************************************
     *************************************************
     ***************Coded by 3r0rXx********************
     *************************************************
     *************************************************
     */
    public class Server : IServer
    {
        public IPAddress Ip { get; private set; }
        public int Port { get; private set; }
        public int Xmx { get; private set; }
        public int Xms { get; private set; }
        public string ServerPath { get; set; }
        public string MCOutput { get; private set; }
        public List<Client> Connection = new List<Client>();

        private TcpListener tcpServer;
        public NetworkStream tcpStream;

        public void Init(string _ip, int _port, int _Xmx = 2048, int _Xms = 512, string _serverPath = "craftbukkit-1.5.2-R1.0.jar")
        {
            if (_ip == "")
            {
                Ip = IPAddress.Any;
            }
            else
            {
                Ip = IPAddress.Parse(_ip);
            }
            Port = _port;
            tcpServer = new TcpListener(Ip, Port);
            Xmx = _Xmx;
            Xms = _Xms;
            ServerPath = _serverPath;

            #region startMc
            Process Server = new Process();
            ProcessStartInfo ServerStartInfo = new ProcessStartInfo(@"C:\Program Files\Java\jre1.8.0_20\bin\java.exe");
            ServerStartInfo.Arguments = "-Xmx" + Xmx + "M -Xms" + Xms + "M -jar " + ServerPath;
            ServerStartInfo.CreateNoWindow = true;
            ServerStartInfo.RedirectStandardOutput = true;
            ServerStartInfo.RedirectStandardInput = true;
            ServerStartInfo.RedirectStandardError = true;
            ServerStartInfo.UseShellExecute = false;
            Server.StartInfo = ServerStartInfo;
            Server.ErrorDataReceived += Server_Error;
            Server.OutputDataReceived += Server_Output;
            Server.Start();
            Server.BeginErrorReadLine();
            Server.BeginOutputReadLine();
            //Server.WaitForExit();
            #endregion
            
        }

        private void Server_Error(object sender, DataReceivedEventArgs e)
        {
            if (e.Data == ">")
            {

            }
            else
            {
                MCOutput = e.Data;
                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine(e.Data);
            }
        }

        private void Server_Output(object sender, DataReceivedEventArgs e)
        {
            if (e.Data == ">")
            {

            }
            else
            {
                MCOutput = e.Data;
                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine(e.Data);
            }
        }

        public void Run()
        {
            tcpServer.Start();
            new Thread(new ThreadStart(Receive)).Start();
        }

        public void Receive()
        {
            Console.WriteLine("Server started...");
            while (true)
            {
                TcpClient tmp = tcpServer.AcceptTcpClient();
                tcpStream = tmp.GetStream();
                Client connection = new Client();
                connection.nStream = tcpStream;
                connection.sReader = new StreamReader(tcpStream);
                connection.sWriter = new StreamWriter(tcpStream);
                Connection.Add(connection);
                Console.WriteLine("Client has connected!");
                Send();
            }
        }

        public void Send()
        {

            foreach (var connections in Connection)
            {
                try
                {
                    connections.sWriter.Write(MCOutput);
                    connections.sWriter.Flush();
                }
                catch
                {
                    Connection.Remove(connections);
                   
                }
            }
        }
    }
}


Client:



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using ServerData;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Diagnostics;


namespace Client
{
    class Program
    {
        const int PORT_NO = 8000;
        const string SERVER_IP = "127.0.0.1";
        static void Main(string[] args)
        {
         
            TcpClient client = new TcpClient(SERVER_IP, PORT_NO);
            NetworkStream nwStream = client.GetStream();
            byte[] buffer = new byte[2048];

            StringBuilder messageData = new StringBuilder();

            int bytes = -1;


            while (client.Connected)
            {
                    
                    bytes = nwStream.Read(buffer, 0, buffer.Length);

                    Decoder decoder = Encoding.UTF8.GetDecoder();
                    char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
                    decoder.GetChars(buffer, 0, bytes, chars, 0);

                    messageData.Append(chars);
                    Console.WriteLine(messageData.ToString());
            }


        }
    }
}


Hier ist das Problem was ich nicht verstehe
A: Lese ich den Stream mit diesen Code aus erhalte ich nur 1x mal die ausgabe.
Lese ich ihn aber mit einen StreamReader aus erhalte ich garnichts
B: Warum hält die schleife sozusagen bevor sie das 2x Console.WriteLine erreicht und überspringt dies?
C: Wie kann ich den Stream denn jetzt dauerhaft auslesen?

W
872 Beiträge seit 2005
vor 9 Jahren

Du rufst nur an einer Stelle im Server Send auf.
Du solltest einen eigenen Thread machen, der empfangene Daten an alle verbundenden Clients schickt.
Am einfachsten hast Du die Clients dazu in einer ConcurrentBag<T>. Wenn dann der Server von Minecraft liest, rufst Du dort Send auf.

O
Odin008 Themenstarter:in
58 Beiträge seit 2013
vor 9 Jahren

Entweder bin ich zu doof dafür oder es bringt nichts denn ich erhalte immernoch keine Informationen am Client....

4.221 Beiträge seit 2005
vor 9 Jahren

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

O
Odin008 Themenstarter:in
58 Beiträge seit 2013
vor 9 Jahren

Danke Euch habs problem soweit gelöst nur hab ein weiteres Problem
undzwar ich verbinde mich empfange die Daten und schliessen dann den Client
alles kein Problem
dann versuche ich mich nochmal mit dem Client zu verbinden und der Server schmiert ab mit

Fehlermeldung:
"An unhandled exception of type 'System.InvalidOperationException' occurred in mscorlib.dll

Additional information: Collection was modified; enumeration operation may not execute."

In folgender Zeile:


            [COLOR]foreach (var connections in Connection)
[/color]
            {
                try
                {
                    connections.sWriter.WriteLine(MCOutput);
                    connections.sWriter.Flush();
                }
                catch
                {
                    Connection.Remove(connections);
                    Console.WriteLine("Client remove");
                }
            }

Der Rot makierte Satz löst den fehler aus

Im Server kommt erst die Meldung das der neue Client sich verbunden hat
und danach das der alte Client gelöscht wurde

Wie kann ich jetzt verhindern das der Server desswegen abschmiert?

4.221 Beiträge seit 2005
vor 9 Jahren

Remove innerhalb foreach ist nict erlaubt.

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

O
Odin008 Themenstarter:in
58 Beiträge seit 2013
vor 9 Jahren

Ohh okay und wie entferne ich dann die Clients die nicht mehr verbunden sind?

16.842 Beiträge seit 2008
vor 9 Jahren

Das sind absolute Grundlagen -> Liste duplizieren.
Beachte [Hinweis] Wie poste ich richtig? 1.1.1