簡體   English   中英

在C#WinForms中使用UserControl和Socket

[英]Using UserControls and Sockets in C# WinForms

我是Sockets的新手,如果有人可以提供建議,我將不勝感激。 在我的Windows窗體應用程序中,幾個用戶可以將用戶控件添加到同一窗體並進行管理。 我不確定是否采取了正確的方法。 我的前兩個功能是drawing並添加UserControl 對於繪圖,我只需將Mouse_Move事件的坐標發送給所有客戶端:

private void Form1_MouseMove(object sender, MouseEventArgs e)
    {
        if (canDraw)
        {
            string coords= e.X.ToString() + "|" + e.Y.ToString();
            Sender(coords);
        }
    }

 void Sender(string msg)
 {
        byte[] bytes = new byte[1024];
        bytes = Encoding.UTF8.GetBytes(msg);
        client.Send(bytes);
 }

當我收到字節時,我繪制它們:

 client.Receive(bytes);

 string data = Encoding.UTF8.GetString(bytes);
 //the received data in format "X|Y"
 string[] split_data = data.Split(new Char[] { '|' });
 Draw(Convert.ToInt32(split_data[0]),
     Convert.ToInt32(split_data[1]));

繪制方法:

void Draw(int x, int y)
{
        Graphics graphics = CreateGraphics();
        graphics.FillEllipse(new SolidBrush(Color.Black), x, y, 5, 5);
}

此時一切正常。 現在,我嘗試將UserControl添加到表單並將其發送給所有客戶端。 我只是在需要添加控件時發送一些符號,然后創建新的userControl

 private void AddRectButton_Click(object sender, EventArgs e)
 {            
    Sender("RectControl|");            
 } 

當我收到:

 client.Receive(bytes);
 if (bytes.Length != 0)
 {
   string data = Encoding.UTF8.GetString(bytes);
   string[] split_data = data.Split(new Char[] { '|' });

   if (split_data[0] == "RectControl")
   {
       this.Invoke(new MethodInvoker(delegate
       {
          RectControl control = new RectControl();
          this.Controls.Add(control);
       }));
   }
  else 
  {
     Draw(Convert.ToInt32(split_data[0]),
     Convert.ToInt32(split_data[1]));
  }

我不確定我是否做得對,也許還有另一種實現方法? 另外,當一個客戶端對userControl進行一些更改(例如,移動,控件內容的操作等)時,我將必須跟蹤所有更改並將其發送給所有客戶端。 我如何才能確切知道已更改了哪個控件以將這些更改應用於其余控件?

PLED提供了很好的建議。 我會補充:

目前尚不清楚您使用的是哪種傳輸協議。 如果是UDP,則可能會丟棄數據包,因此某些客戶端可能會看到其他客戶端看不到的新控件或移動的控件。

我猜您使用TCP來保證傳遞和擁塞控制。 請記住,TCP是流協議。 這意味着,當您發送50字節的消息時,您可能會在一個接收呼叫中一次全部接收到該消息,或者一次1字節多達50個不同的接收呼叫。

另外,您可能在一個“接聽”電話中收到多條消息。

查找“ TCP幀”。 在每個接收上,請確保您讀入所有完整的消息,保留下一條消息中所包含的所有額外字節,然后進行下一個接收呼叫。 簡化成幀的一種方法是在每條消息之前使用4個字節的長度前綴,這樣您就可以知道何時閱讀完整的消息。

我還建議您查找protobuf-net(或Google協議緩沖區的另一種實現),它將為您處理序列化,並允許您處理簡單類型,其中消息的每個字段都是該類型的屬性。 這樣可以避免解析字符串。 protobuf-net是可擴展的,因此,如果您決定以后再向消息中添加新字段,它會更容易並且不會破壞現有的已部署版本。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM