开发者

C# problem with token passing synchronization in client-server chat

开发者 https://www.devze.com 2023-03-07 04:41 出处:网络
I\'ve got a problem with passing tokens in C# client-server application. Could you help me with that please? Firstly I describe the situation, secondly I paste some source code, thirdly i will give a

I've got a problem with passing tokens in C# client-server application. Could you help me with that please? Firstly I describe the situation, secondly I paste some source code, thirdly i will give a link to visual studio solutions.

So the situation is like this: i've created multithreaded client-server tcp chat. Everything is working fine, all users can write message at one time, and all users see everything.

The problem is that i need server to pass token to one user at a time, so only one user can send messages at time, when all other users will be only listening. Token should be passing to users in order of joining server for amount of 10 seconds.

Example: user A joined server, user B joined server, user C joined server. Server passes token to user A for 10 seconds, and user A can write messages for 10 seconds (for example, sending button is disabled by default, and server pass token = true to client. If token is true, sending button is enabled for 10 seconds, and then token is false again). After 10 seconds server pass token to user B, and user B can write messages for 10 seconds etc.. How to do this?

Here is a source code of a server:

namespace Serverchat
{
class Serwer
{
    public static Hashtable klienci = new Hashtable();

    static void Main(string[] args)
    {
        IPAddress IP = IPAddress.Parse("127.0.0.1");
        int port = 8888;

        TcpListener serwer = new TcpListener(IP, port);
        TcpClient gniazdo = default(TcpClient);

        serwer.Start();
        Console.WriteLine("Token passing simulation\r\nAddress: "+IP+":"+port+"\r\n");

        while (true)
        {
            gniazdo = serwer.AcceptTcpClient();
            byte[] odczyt = new byte[10024];
            string odczytsub = "";

            gniazdo.GetStream().Read(odczyt, 0, gniazdo.ReceiveBufferSize);
            odczytsub = (Encoding.ASCII.GetString(odczyt)).Substring(0, (Encoding.ASCII.GetString(odczyt)).IndexOf("~"));
            klienci.Add(odczytsub, gniazdo);
            rozglos("", odczytsub);
            Console.WriteLine(odczytsub + " joined server.");
            obslugaKlienta klient = new obslugaKlienta();
            klient.startObslugiKlienta(gniazdo, odczytsub);
        }
    }

    public static void rozglos(string wiadomosc, string nazwaUzytkownika)
    {
        foreach (DictionaryEntry klient in klienci)
        {
            TcpClient gniazdo = (TcpClient)klient.Value;
            Byte[] zapis = null;

            if (wiadomosc != "")
            {
                zapis = Encoding.ASCII.GetBytes(nazwaUzytkownika + ":" + wiadomosc + "`");
            }
            else
            {
                zapis = Encoding.ASCII.GetBytes(nazwaUzytkownika + " joined server:");
            }
            gniazdo.GetStream().Write(zapis, 0, zapis.Length);
            gniazdo.GetStream().Flush();
        }
    }
}

public class obslugaKlienta
{
    TcpClient gniazdo;
    string klient;

    public void startObslugiKlienta(TcpClient gniazdo, string klient)
    {
        this.gniazdo = gniazdo;
        this.klient = klient;
        Thread klientWatek = new Thread(komunikacja);
        klientWatek.Start();
    }

    private void komunikacja()
    {
        byte[] odczyt = new byte[10024];
        string odczyt开发者_Python百科sub = "";

        while (true)
        {
            gniazdo.GetStream().Read(odczyt, 0, gniazdo.ReceiveBufferSize);
            odczytsub = Encoding.ASCII.GetString(odczyt).Substring(0, Encoding.ASCII.GetString(odczyt).IndexOf("~"));
            Console.WriteLine(klient + ": " + odczytsub);
            Serwer.rozglos(Convert.ToString(odczytsub), klient);
        }
    }
}
}

For the record, rozglos is a function, that broadcasts messagess to everyone.

Here is source code of a client:

namespace TRKlient
{
public partial class Klient : Form
{
    TcpClient gniazdo = new TcpClient();
    byte[] zapis;
    string dane = null;

    private void buttonWyslij_Click(object sender, EventArgs e) // Sending message
    {
        zapis = Encoding.ASCII.GetBytes(tbWiadomosc.Text + "~");
        gniazdo.GetStream().Write(zapis, 0, zapis.Length);
        gniazdo.GetStream().Flush();
    }

    private void buttonPolacz_Click(object sender, EventArgs e) // Connecting with server
    {
        dane = "Connected with Token Ring.";
        wyswietlWiadomosc();
        gniazdo.Connect(tbIP.Text, 8888);
        zapis = Encoding.ASCII.GetBytes(tbUser.Text + "~");
        gniazdo.GetStream().Write(zapis, 0, zapis.Length);
        gniazdo.GetStream().Flush();
        Thread klientWatek = new Thread(odbierzWiadomosc);
        klientWatek.Start();
        buttonPolacz.Enabled = false;
    }

    private void odbierzWiadomosc() // Reading data from stream
    {
        while (true)
        {
            byte[] odczyt = new byte[10024];
            gniazdo.GetStream().Read(odczyt, 0, gniazdo.ReceiveBufferSize);
            dane = Encoding.ASCII.GetString(odczyt);
            wyswietlWiadomosc();
        }
    }

    private void wyswietlWiadomosc() // Shows received messages in chat textbox
    {
        if (this.InvokeRequired)
            this.Invoke(new MethodInvoker(wyswietlWiadomosc));
        else
        tbChat.Text += "\r\n # " + dane;
    }

    public Klient() 
    {
        InitializeComponent();
    }
}
}

Here is a link to both solutions in Visual Studio 2010: http://www.speedyshare.com/files/28562696/client-server.rar

Please help me guys, this is very important for me and I've run out of ideas.

You've helped me a lot of times so thanks in advance, Peter.

EDIT : Sending message by client with token could be as simple as sending automaticly first letter of his nickname. Everything can be as simple as possible, I only need working token passing. Thanks for your responses.


let's have a look at the differences between the old and the new requirements:

previously you wanted to send messages vrom a client to a server, and from there to all (other) clients, which works fine if you pass the message as string, without any other protocol ... if a client receives something, you can be sure that's a message string which is supposed to be displayed in your chat text box ...

now things are a bit different: you have to distinguish between messages that are to be displayed, and control messages, that inform about the token ... what you need is some sort of protocol for that ...

something that tells a listener if the message contains a chat-message, or a control message.

control messages inform the client about things like "hey client ... you got the token ... sending is allowed for 10 sec ...", or "your permission to send has been revoked", etc.

based on those messages you can enable/disable your client's send button ...

on the other hand, you will have to implement the servers part aswell: managing the token and sending the appropriate control messages to the clients.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号