2011-05-21 77 views
0

我在C#客户端服务器应用程序中传递令牌时遇到了问题。你能帮我一下吗?首先我描述一下情况,其次我粘贴一些源代码,第三我会给视觉工作室解决方案的链接。在客户端 - 服务器聊天中令牌传递同步的C#问题

因此,情况是这样的:我已经创建了多线程的客户端 - 服务器的TCP聊天。一切工作正常,所有用户都可以一次写信息,所有用户都能看到一切。

的问题是,我需要服务器在一次令牌传递到一个用户,所以只能有一个用户在发送的信息,当所有其他用户将只能听。令牌应该按照连接服务器的顺序传递给用户10秒钟。

示例: 用户A加入服务器,用户B加入服务器,用户C加入服务器。服务器向用户A传递令牌10秒,用户A可以写消息10秒(例如,默认情况下,发送按钮处于禁用状态,服务器向客户端传递令牌= true;如果令牌为true,则发送按钮为10秒,然后令牌再次为假)。 10秒后服务器将令牌传递给用户B,并且用户B可以将消息写入10秒等等。如何做到这一点?

这里是一个服务器的源代码:

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 odczytsub = ""; 

     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); 
     } 
    } 
} 
} 

为了记录在案,rozglos是一个功能,即广播messagess给大家。

这里是一个客户端的源代码:

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(); 
    } 
} 
} 

下面是在Visual Studio 2010中,以这两种解决方案的链接:http://www.speedyshare.com/files/28562696/client-server.rar

请帮我家伙,这对我来说非常重要,我已经没有想法了。

你帮了我很多的时间,以便在此先感谢,彼得。

编辑:通过客户端发送令牌消息可能是因为送他的绰号的全自动第一个字母一样简单。一切都可以尽可能简单,我只需要工作令牌传递。感谢您的回应。

回答

0

,让我们来看看旧的和新的要求之间的差异:

以前你想发送消息VROM客户机到服务器,并从那里所有的(其他)客户端,它工作正常,如果您传递的消息字符串,没有任何其他的协议......如果一个客户端收到的东西,你可以肯定这是这是应该显示在聊天文本框中输入一个消息字符串...

现在事情是有点不同:你必须区分要显示的消息和控制消息,告知令牌......你需要的是某种协议......

这是告诉侦听器消息是否包含聊天消息或控制消息的内容。

控制消息通知客户有关“嘿客户......你得到令牌......允许发送10秒...”,或“您的发送许可已被撤销”等内容。

基于这些消息,您可以启用/禁用客户端的发送按钮...

,另一方面,你将必须实现服务器部分藏汉:管理令牌并发送相应的控制信息到客户端。

+0

感谢您的答复,我明白你的意思。不幸的是我还是不知道该怎么做,在实践中:( – Peter 2011-05-21 02:13:02

+0

首先你必须定义这些消息的协议,你可以定义自己的,或实现类似的IRC协议(http://www.faqs。组织/ RFC文档/ rfc1459.html),但IRC似乎有点过大了您的应用程序。也许只是前面加上味精和令牌控制消息的每个聊天消息可能是“TOKEN <时间(秒)>”,你能辨别聊天信息从一个令牌中查看第一个单词,然后将字符串赋予相应的处理函数(chat-message? - >输出到用户/控制消息? - >执行其他操作) – DarkSquirrel42 2011-05-22 20:19:07