2011-05-21 91 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