Avatar billede Slettet bruger
12. maj 2006 - 16:06 Der er 17 kommentarer og
1 løsning

Server / klient program

Hej eksperter, jeg har brug for nogle gode råd!

Jeg skal i gang med at lave et server og et klient program der connecter op mod hinanden, vil lige forklare det kort her:

Server:
Skal kunne håndtere flere klienter, man skal have et overblik over hvilke klienter der er forbundet, samt eks. sende en besked til én bestemt klient.

Klient:
Skal forbinde op mod serveren, og skal kunne sende oplysninger til serveren, evt. også filer.


Den største udfordring jeg ikke kan gennemtænke er hvordan man løser det med at holde styre på klienterne på serveren og hvordan man kan kommunikere med en bestemt...
Avatar billede arne_v Ekspert
12. maj 2006 - 16:26 #1
klassisk loesning er jo:
  accept connection
  create client handler objekt
  gem client i collection
  start traad for client
Avatar billede Slettet bruger
12. maj 2006 - 16:42 #2
Hej Arne,
Kan jeg få dig til at beskrive de steps lidt dybere, evt. med kode henvisning?
Avatar billede arne_v Ekspert
12. maj 2006 - 16:53 #3
jeg lavede noget kode til et andet spoergsmaal engang

ikke nogen speciel god kode, men det boer illustrere teknikken
Avatar billede arne_v Ekspert
12. maj 2006 - 16:58 #4
using System;
using System.Collections;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;

class ChatMain
{
    public static void Main(string[] args)
    {
        Server srv = new Server();
        srv.Run();
    }
}

class Server
{
    private ArrayList allclients;
    public void Run()
    {
        allclients = new ArrayList();
        TcpListener server = new TcpListener(IPAddress.Any, 50000);
        server.Start();
        while(true)
        {
            TcpClient client = server.AcceptTcpClient();
            ClientHandler ch = new ClientHandler(client, this);
            allclients.Add(ch);
            (new Thread(new ThreadStart(ch.Run))).Start();
        }
    }
    public void SendAll(string msg)
    {
        foreach(ClientHandler ch in allclients)
        {
            ch.Send(msg);
        }
    }
    public void Remove(ClientHandler ch)
    {
        allclients.Remove(ch);
    }
}

class ClientHandler
{
    private StreamReader rdr;
    private StreamWriter wrt;
    private Server srv;
    public ClientHandler(TcpClient cli, Server srv)
    {
        rdr = new StreamReader(cli.GetStream());
        wrt = new StreamWriter(cli.GetStream());
        this.srv = srv;
    }
    public void Run()
    {
        while(true)
        {
            string line = rdr.ReadLine();
            string cmd = line.Split(" ".ToCharArray())[0];
            if(cmd == "SEND")
            {
                srv.SendAll(line.Substring(5));
            }
            else if(cmd == "EXIT")
            {
                srv.Remove(this);
                return;
            }
        }
    }
    public void Send(string msg)
    {
        lock(wrt)
        {
            wrt.WriteLine(msg);
            wrt.Flush();
        }
    }
}
Avatar billede arne_v Ekspert
12. maj 2006 - 17:03 #5
using System;
using System.IO;
using System.Net.Sockets;
using System.Threading;

class ChatClient
{
    public static void Main(string[] args)
    {
        TcpClient client = new TcpClient("localhost", 50000);
        StreamWriter wrt = new StreamWriter(client.GetStream());
        (new Thread(new ThreadStart((new Reader(client)).Run))).Start();
        string line;
        while((line = Console.ReadLine()) != null)
        {
            wrt.WriteLine("SEND " + line);
            wrt.Flush();
        }
        wrt.WriteLine("EXIT");
        wrt.Flush();
        wrt.Close();
        client.Close();
    }
}

class Reader
{
    private StreamReader rdr;
    public Reader(TcpClient cli)
    {
        rdr = new StreamReader(cli.GetStream());
    }
    public void Run()
    {
        try
        {
            string line;
            while((line = rdr.ReadLine()) != null)
            {
                Console.WriteLine(line);
            }
        }
        catch(Exception)
        {
            // nothing
        }
    }
}
Avatar billede Slettet bruger
12. maj 2006 - 17:43 #6
Hej Arne,
Tak - hvordan kan jeg så snakke med en specifik klient fra serveren af?
Jeg kan se at alle klienterne bliver samlet i en arrayliste, men hvordan går jeg ind og finder feks klienten fra ip 192.168.10.12 ?

Og jeg skal jo sådan set også kunne identificere klienten på serveren hver gang den evt skulle sende noget, så jeg kan håndtere det som data fra denne klient.
Avatar billede arne_v Ekspert
12. maj 2006 - 17:55 #7
enten kan du loebe ArrayListen igennem og finde den rigtige client

eller du kan erstatte den ArrayList med en Hashtable
Avatar billede Slettet bruger
12. maj 2006 - 17:57 #8
Smid et eksempel på det, så får du point, hvis jeg får yderligere spørgsmål kan vi evt. snakkes ved - det udløser selvfølgelig flere point.

Tak for det i hvertfald
Avatar billede Slettet bruger
12. maj 2006 - 17:58 #9
Et eks på hvordan jeg finder eks 192.168.10.12, og sender en besked, eks HELLO :o)
Avatar billede arne_v Ekspert
12. maj 2006 - 18:58 #10
jeg tilretter eksemplet senere
Avatar billede arne_v Ekspert
13. maj 2006 - 02:26 #11
using System;
using System.Collections;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;

class ChatMain
{
    public static void Main(string[] args)
    {
        Server srv = new Server();
        srv.Run();
    }
}

class Server
{
    private ArrayList allclients;
    public void Run()
    {
        allclients = new ArrayList();
        TcpListener server = new TcpListener(IPAddress.Any, 50000);
        server.Start();
        while(true)
        {
            TcpClient client = server.AcceptTcpClient();
            ClientHandler ch = new ClientHandler(client, this);
            allclients.Add(ch);
            (new Thread(new ThreadStart(ch.Run))).Start();
        }
    }
    public void SendAll(string msg)
    {
        foreach(ClientHandler ch in allclients)
        {
            ch.Send(msg);
        }
    }
    public void SendOne(string msg, string address)
    {
        foreach(ClientHandler ch in allclients)
        {
            if(ch.Remote.IndexOf(address) == 0)
            {
                ch.Send(msg);
            }
        }
    }
    public void Remove(ClientHandler ch)
    {
        allclients.Remove(ch);
    }
}

class ClientHandler
{
    private string remote;
    private StreamReader rdr;
    private StreamWriter wrt;
    private Server srv;
    public ClientHandler(TcpClient cli, Server srv)
    {
        remote = cli.Client.RemoteEndPoint.ToString();
        rdr = new StreamReader(cli.GetStream());
        wrt = new StreamWriter(cli.GetStream());
        this.srv = srv;
    }
    public void Run()
    {
        while(true)
        {
            string line = rdr.ReadLine();
            string[] parts = line.Split(" ".ToCharArray());
            string cmd = parts[0];
            if(cmd == "SEND")
            {
                string address = parts[1];
                if(address == "*")
                {
                    srv.SendAll(line.Substring(cmd.Length + address.Length + 2));
                }
                else
                {
                    srv.SendOne(line.Substring(cmd.Length + address.Length + 2), address);
                }
            }
            else if(cmd == "EXIT")
            {
                srv.Remove(this);
                return;
            }
        }
    }
    public void Send(string msg)
    {
        lock(wrt)
        {
            wrt.WriteLine(msg);
            wrt.Flush();
        }
    }
    public string Remote
    {
        get
        {
            return remote;
        }
    }
}
Avatar billede arne_v Ekspert
13. maj 2006 - 02:28 #12
Hvis man i client skriver:

* Hello

får alle client beskeden.

Hvis man i client skriver:

192.168.10.12 Hello

så er det kun client 192.168.10.12 som får beskeden

P.g.a. den måde jeg tester så vil:

192.168 Hello

gå til alle 192.168.*.*

men det kan du jo selv arbejde videre med
Avatar billede arne_v Ekspert
13. maj 2006 - 02:28 #13
kode kræver .NET 2.0 fordi TcpCLient Client property er protected i .NET 1.1
Avatar billede arne_v Ekspert
13. maj 2006 - 02:29 #14
og client tester ikke på om der er det krævede mellemrum i input

hvis ikke => server crasher

men det kan du jo også forbedre
Avatar billede arne_v Ekspert
13. maj 2006 - 02:29 #15
og et svar
Avatar billede Slettet bruger
13. maj 2006 - 18:52 #16
Hej Arne,
Jeg har nu implementeret det og tilpasset det min winform...
Jeg har et problem, når jeg vil lukke min winform hænger den pga:

            while (true)
            {
                TcpClient client = server.AcceptTcpClient();
                ClientHandler ch = new ClientHandler(client, this);
                allclients.Add(ch);
                GetAgents();
                (new Thread(new ThreadStart(ch.Run))).Start();
            }

Har du en idé til hvordan jeg kan undgå at den står der og hænger, og faktisk forhindrer mig i at lukke programmet.
Avatar billede arne_v Ekspert
13. maj 2006 - 21:43 #17
enten skal du have stppet alle traade

ellers prøv:

        Application.Run(new MainForm());
        Application.Exit();
        Environment.Exit(0);
Avatar billede Slettet bruger
14. maj 2006 - 10:39 #18
Environment.Exit(0);

Det er bare guldet, tak ;)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester