程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> C# 2.0套接字編程實例初探

C# 2.0套接字編程實例初探

編輯:關於C#

首先從原理上解釋一下采用Socket接口的網絡通訊,這裡以最常用的C/S模式作為范例,首先,服務端有一個進程(或多個進程)在指定的端口等待客戶來連接,服務程序等待客戶的連接信息,一旦連接上之後,就可以按設計的數據交換方法和格式進行數據傳輸。客戶端在需要的時刻發出向服務端的連接請求。這裡為了便於理解,提到了一些調用及其大致的功能。使用socket調用後,僅產生了一個可以使用的socket描述符,這時還不能進行通信,還要使用其他的調用,以使得socket所指的結構中使用的信息被填寫完。

在使用TCP協議時,一般服務端進程先使用socket調用得到一個描述符,然後使用bind調用將一個名字與socket描述符連接起來,對於Internet域就是將Internet地址聯編到socket。之後,服務端使用listen調用指出等待服務請求隊列的長度。然後就可以使用accept調用等待客戶端發起連接,一般是阻塞等待連接,一旦有客戶端發出連接,accept返回客戶的地址信息,並返回一個新的socket描述符,該描述符與原先的socket有相同的特性,這時服務端就可以使用這個新的socket進行讀寫操作了。一般服務端可能在accept返回後創建一個新的進程進行與客戶的通信,父進程則再到accept調用處等待另一個連接。客戶端進程一般先使用socket調用得到一個socket描述符,然後使用connect向指定的服務器上的指定端口發起連接,一旦連接成功返回,就說明已經建立了與服務器的連接,這時就可以通過socket描述符進行讀寫操作了。

.NetFrameWork為Socket通訊提供了System.Net.Socket命名空間,在這個命名空間裡面有以下幾個常用的重要類分別是:

·Socket類 這個低層的類用於管理連接,WebRequest,TcpClient和UdpClient在內部使用這個類。

·NetworkStream類 這個類是從Stream派生出來的,它表示來自網絡的數據流

·TcpClient類 允許創建和使用TCP連接

·TcpListener類 允許監聽傳入的TCP連接請求

·UdpClient類 用於UDP客戶創建連接(UDP是另外一種TCP協議,但沒有得到廣泛的使用,主要用於本地網絡)

下面我們來看一個基於Socket的雙機通信代碼的C#版本

首先創建Socket對象的實例,這可以通過Socket類的構造方法來實現:

public Socket(AddressFamily addressFamily,SocketType socketType,ProtocolType protocolType);

其中,addressFamily 參數指定 Socket 使用的尋址方案,socketType 參數指定 Socket 的類型,protocolType 參數指定 Socket 使用的協議。

下面的示例語句創建一個 Socket,它可用於在基於 TCP/IP 的網絡(如 Internet)上通訊。

Socket temp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

若要使用 UDP 而不是 TCP,需要更改協議類型,如下面的示例所示:

Socket temp = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

一旦創建 Socket,在客戶端,你將可以通過Connect方法連接到指定的服務器(你可以在Connect方法前Bind端口,就是以指定的端口發起連接,如果不事先Bind端口號的話,系統會默認在1024到5000隨機綁定一個端口號),並通過Send方法向遠程服務器發送數據,而後可以通過Receive從服務端接收數據;而在服務器端,你需要使用Bind方法綁定所指定的接口使Socket與一個本地終結點相聯,並通過Listen方法偵聽該接口上的請求,當偵聽到用戶端的連接時,調用Accept完成連接的操作,創建新的Socket以處理傳入的連接請求。使用完 Socket 後,使用 Close 方法關閉 Socket。

可以看出,以上許多方法包含EndPoint類型的參數,在Internet中,TCP/IP 使用一個網絡地址和一個服務端口號來唯一標識設備。網絡地址標識網絡上的特定設備;端口號標識要連接到的該設備上的特定服務。網絡地址和服務端口的組合稱為終結點,在 .NET 框架中正是由 EndPoint 類表示這個終結點,它提供表示網絡資源或服務的抽象,用以標志網絡地址等信息。.Net同時也為每個受支持的地址族定義了 EndPoint 的子代;對於 IP 地址族,該類為 IPEndPoint。IPEndPoint 類包含應用程序連接到主機上的服務所需的主機和端口信息,通過組合服務的主機IP地址和端口號,IPEndPoint 類形成到服務的連接點。

用到IPEndPoint類的時候就不可避免地涉及到計算機IP地址,System.Net命名空間中有兩種類可以得到IP地址實例:

·IPAddress類:IPAddress 類包含計算機在 IP 網絡上的地址。其Parse方法可將 IP 地址字符串轉換為 IPAddress 實例。下面的語句創建一個 IPAddress 實例:

IPAddress myIP = IPAddress.Parse("192.168.0.1");

需要知道的是:Socket 類支持兩種基本模式:同步和異步。其區別在於:在同步模式中,按塊傳輸,對執行網絡操作的函數(如 Send 和 Receive)的調用一直等到所有內容傳送操作完成後才將控制返回給調用程序。在異步模式中,是按位傳輸,需要指定發送的開始和結束。同步模式是最常用的模式,我們這裡的例子也是使用同步模式。

下面看一個完整的例子,client向server發送一段測試字符串,server接收並顯示出來,給予client成功響應。

//client端
using System;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace socketsample
{
 class Class1
 {
  static void Main()
  {
   try
   {
    int port = 2000;
    string host = "127.0.0.1";
    IPAddress ip = IPAddress.Parse(host);
    IPEndPoint ipe = new IPEndPoint(ip, port);//把ip和端口轉化為IPEndPoint實例
    Socket c = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//創建一個Socket
    Console.WriteLine("Conneting...");
    c.Connect(ipe);//連接到服務器
    string sendStr = "hello!This is a socket test";
    byte[] bs = Encoding.ASCII.GetBytes(sendStr);
    Console.WriteLine("Send Message");
    c.Send(bs, bs.Length, 0);//發送測試信息
    string recvStr = "";
    byte[] recvBytes = new byte[1024];
    int bytes;
    bytes = c.Receive(recvBytes, recvBytes.Length, 0);//從服務器端接受返回信息
    recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);
    Console.WriteLine("Client Get Message:{0}", recvStr);//顯示服務器返回信息
    c.Close();
   }
   catch (ArgumentNullException e)
   {
    Console.WriteLine("ArgumentNullException: {0}", e);
   }
   catch (SocketException e)
   {
    Console.WriteLine("SocketException: {0}", e);
   }
   Console.WriteLine("Press Enter to Exit");
   Console.ReadLine();
  }
 }
}
//server端
using System;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace Project1
{
 class Class2
 {
  static void Main()
  {
   try
   {
    int port = 2000;
    string host = "127.0.0.1";
    IPAddress ip = IPAddress.Parse(host);
    IPEndPoint ipe = new IPEndPoint(ip, port);
    Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//創建一個Socket類
    s.Bind(ipe);//綁定2000端口
    s.Listen(0);//開始監聽
    Console.WriteLine("Wait for connect");
    Socket temp = s.Accept();//為新建連接創建新的Socket。
    Console.WriteLine("Get a connect");
    string recvStr = "";
    byte[] recvBytes = new byte[1024];
    int bytes;
    bytes = temp.Receive(recvBytes, recvBytes.Length, 0);//從客戶端接受信息
    recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);
    Console.WriteLine("Server Get Message:{0}",recvStr);//把客戶端傳來的信息顯示出來
    string sendStr = "Ok!Client Send Message Sucessful!";
    byte[] bs = Encoding.ASCII.GetBytes(sendStr);
    temp.Send(bs, bs.Length, 0);//返回客戶端成功信息
    temp.Close();
    s.Close();
   }
   catch (ArgumentNullException e)
   {
    Console.WriteLine("ArgumentNullException: {0}", e);
   }
   catch (SocketException e)
   {
    Console.WriteLine("SocketException: {0}", e);
   }
   Console.WriteLine("Press Enter to Exit");
   Console.ReadLine();
  }
 }
}

上面的例子是用的Socket類,System.Net.Socket命名空間還提供了兩個抽象高級類TCPClient和UDPClient和用於通訊流處理的NetWorkStream,讓我們看下例子

客戶端

TcpClient tcpClient=new TcpCLient(主機IP,端口號);
NetworkStream ns=tcp.Client.GetStream();

服務端

TcpListener tcpListener=new TcpListener(監聽端口);
tcpListener.Start();
TcpClient tcpClient=tcpListener.AcceptTcpClient();
NetworkStream ns=tcpClient.GetStream();

服務端用TcpListener監聽,然後把連接的對象實例化為一個TcpClient,調用TcpClient.GetStream()方法,返回網絡流實例化為一個NetworlStream流,下面就是用流的方法進行Send,Receive

如果是UdpClient的話,就直接UdpClient實例化,然後調用UdpClient的Send和Receive方法,需要注意的事,UdpClient沒有返回網絡流的方法,就是說沒有GetStream方法,所以無法流化,而且使用Udp通信的時候,不要服務器監聽。

現在我們大致了解了.Net Socket通信的流程,下面我們來作一個稍微復雜點的程序,一個廣播式的C/S聊天程序。

客戶端設計需要一個1個ListBox,用於顯示聊天內容,一個TextBox輸入你要說的話,一個Button發送留言,一個Button建立連接。

點擊建立連接的Button後出來一個對話框,提示輸入連接服務器的IP,端口,和你的昵稱,啟動一個接受線程,負責接受從服務器傳來的信息並顯示在ListBox上面。

服務器端2個Button,一個啟動服務,一個T掉已建立連接的客戶端,一個ListBox顯示連接上的客戶端的Ip和端口。

比較重要的地方是字符串編碼的問題,需要先把需要傳送的字符串按照UTF8編碼,然後接受的時候再還原成為GB2312,不然中文顯示會是亂碼。

還有一個就是接收線程,我這裡簡單寫成一個While(ture)循環,不斷判斷是否有信息流入,有就接收,並顯示在ListBox上,這裡有問題,在.Net2.0裡面,交錯線程修改窗體空間屬性的時候會引發一個異常,不可以直接修改,需要定義一個委托來修改。

當客戶端需要斷開連接的時候,比如點擊窗體右上角的XX,就需要定義一個this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Closing);(.Net2.0是FormClosing系統事件),在Closing()函數裡面,發送Close字符給服務端,服務器判斷循環判斷所有的連接上的客戶端傳來的信息,如果是以Close開頭,斷開與其的連接。看到這裡,讀者就會問了,如果我在聊天窗口輸入Close是不是也斷開連接呢?不是的,在聊天窗口輸入的信息傳給服務器的時候開頭都要加上Ip信息和昵稱,所以不會沖突。

客戶端

// Form1.Designer.cs
namespace ClientTest
{
  partial class Form1
  {
    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;
    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
      if (disposing && (components != null))
      {
        components.Dispose();
      }
      base.Dispose(disposing);
    }
    #region Windows Form Designer generated code
    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
      this.listBox1 = new System.Windows.Forms.ListBox();
      this.button1 = new System.Windows.Forms.Button();
      this.textBox1 = new System.Windows.Forms.TextBox();
      this.button3 = new System.Windows.Forms.Button();
      this.SuspendLayout();
      //
      // listBox1
      //
      this.listBox1.FormattingEnabled = true;
      this.listBox1.ItemHeight = 12;
      this.listBox1.Location = new System.Drawing.Point(12, 12);
      this.listBox1.Name = "listBox1";
      this.listBox1.Size = new System.Drawing.Size(268, 148);
      this.listBox1.TabIndex = 0;
      //
      // button1
      //
      this.button1.Location = new System.Drawing.Point(12, 166);
      this.button1.Name = "button1";
      this.button1.Size = new System.Drawing.Size(268, 35);
      this.button1.TabIndex = 1;
      this.button1.Text = "連接";
      this.button1.UseVisualStyleBackColor = true;
      this.button1.Click += new System.EventHandler(this.button1_Click);
      //
      // textBox1
      //
      this.textBox1.Location = new System.Drawing.Point(12, 207);
      this.textBox1.Multiline = true;
      this.textBox1.Name = "textBox1";
      this.textBox1.Size = new System.Drawing.Size(211, 54);
      this.textBox1.TabIndex = 3;
      //
      // button3
      //
      this.button3.Location = new System.Drawing.Point(229, 207);
      this.button3.Name = "button3";
      this.button3.Size = new System.Drawing.Size(51, 54);
      this.button3.TabIndex = 4;
      this.button3.Text = "發言";
      this.button3.UseVisualStyleBackColor = true;
      this.button3.Click += new System.EventHandler(this.button3_Click);
      //
      // Form1
      //
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
      this.ClientSize = new System.Drawing.Size(292, 273);
      this.Controls.Add(this.button3);
      this.Controls.Add(this.textBox1);
      this.Controls.Add(this.button1);
      this.Controls.Add(this.listBox1);
      this.Name = "Form1";
      this.Text = "客戶端";
      this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Closing);
      this.Load += new System.EventHandler(this.Form1_Load);
      this.ResumeLayout(false);
      this.PerformLayout();
    }
    #endregion
    private System.Windows.Forms.ListBox listBox1;
    private System.Windows.Forms.Button button1;
    private System.Windows.Forms.TextBox textBox1;
    private System.Windows.Forms.Button button3;
  }
}
//Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.IO;
using System.Threading;
namespace ClientTest
{
  public partial class Form1 : Form
  {
    Socket client;
    public string host = "";//要連接的服務器IP
    int port = 2000;
    Thread Data;
    public string nick = "";//給自己起一個昵稱,呵呵
    Encoding utf8 = Encoding.UTF8;
    Encoding gb2312 = Encoding.GetEncoding("GB2312");
    delegate void SetSafe(string text);
    public Form1()
    {
      InitializeComponent();
    }
    private void button1_Click(object sender, EventArgs e)//連接服務器
    {
      Form2 frm2 = new Form2();
      frm2.ShowDialog();//顯示一個對話框,輸入服務器IP和自己的昵稱
      host = frm2.textBox2.Text;
      nick=frm2.textBox1.Text;
      try
      {
        client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        client.Connect(host, port);//連接服務器
      }
      catch (Exception ex)
      {
        MessageBox.Show(ex.Message);
      }
    }
    private void Form1_Load(object sender, EventArgs e)//窗體載入時候開啟一個數據處理線程,處理從服務器得到的數據
    {
      Data = new Thread(new ThreadStart(DataStart));
      Data.Start();
    }
    public void DataStart()//只要能從服務器得到數據,就顯示在ListBox上,這個過程一直循環
    {
      while (true)
      {
        try
        {
          NetworkStream ns = new NetworkStream(client);
          StreamReader reader = new StreamReader(ns);
          string result =reader.ReadLine();
          byte[] u = utf8.GetBytes(result);
          byte[] gb = Encoding.Convert(utf8, gb2312, u);
          string sGb = gb2312.GetString(gb);
          AddList(sGb);
          reader.Close();
          ns.Close();
        }
        catch { }
        Thread.Sleep(1000);
      }
    }
    private void button3_Click(object sender, EventArgs e)//發言
    {
      try
      {
        string sendString = "("+ client.LocalEndPoint.ToString()+")"+nick+"說"+textBox1.Text + "\r\n";
        byte[] butf = utf8.GetBytes(sendString);
        client.Send(butf);//按照昵稱(IP)說的話的格式發送給服務器
      }
      catch { }
    }
    private void AddList(object text)
    {
      // InvokeRequired required compares the thread ID of the
      // calling thread to the thread ID of the creating thread.
      // If these threads are different, it returns true.
      if (this.listBox1.InvokeRequired)
      {
        SetSafe d = new SetSafe(AddList);
        this.Invoke(d, new object[] { text });
      }
      else
      {
        this.listBox1.Items.Add(text);
      }
    }
    private void Closing(object sender, System.EventArgs e)//斷開連接,發送服務器"Close"信息
    {
      try
      {
        Data.Abort();
        Byte[] buf = System.Text.Encoding.UTF8.GetBytes("Close" + "\r\n");
        client.Send(buf);
      }
      catch { }
    }
  }
}
//Form2.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace ClientTest
{
  public partial class Form2 : Form
  {
    public Form2()
    {
      InitializeComponent();
    }
    private void button1_Click(object sender, EventArgs e)
    {
      this.Hide();
     
    }
  }
}
服務端
// Form1.Designer.cs
namespace ServerTest
{
  partial class Form1
  {
    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;
    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
      if (disposing && (components != null))
      {
        components.Dispose();
      }
      base.Dispose(disposing);
    }
    #region Windows Form Designer generated code
    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
      this.button1 = new System.Windows.Forms.Button();
      this.listBox1 = new System.Windows.Forms.ListBox();
      this.button2 = new System.Windows.Forms.Button();
      this.SuspendLayout();
      //
      // button1
      //
      this.button1.Location = new System.Drawing.Point(12, 12);
      this.button1.Name = "button1";
      this.button1.Size = new System.Drawing.Size(130, 44);
      this.button1.TabIndex = 0;
      this.button1.Text = "開啟服務";
      this.button1.UseVisualStyleBackColor = true;
      this.button1.Click += new System.EventHandler(this.button1_Click);
      //
      // listBox1
      //
      this.listBox1.FormattingEnabled = true;
      this.listBox1.ItemHeight = 12;
      this.listBox1.Location = new System.Drawing.Point(12, 62);
      this.listBox1.Name = "listBox1";
      this.listBox1.Size = new System.Drawing.Size(268, 196);
      this.listBox1.TabIndex = 1;
      //
      // button2
      //
      this.button2.Location = new System.Drawing.Point(150, 12);
      this.button2.Name = "button2";
      this.button2.Size = new System.Drawing.Size(130, 44);
      this.button2.TabIndex = 2;
      this.button2.Text = "T人";
      this.button2.UseVisualStyleBackColor = true;
      this.button2.Click += new System.EventHandler(this.button2_Click);
      //
      // Form1
      //
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
      this.ClientSize = new System.Drawing.Size(292, 273);
      this.Controls.Add(this.button2);
      this.Controls.Add(this.listBox1);
      this.Controls.Add(this.button1);
      this.Name = "Form1";
      this.Text = "服務端";
      this.ResumeLayout(false);
      this.FormClosing+=new System.Windows.Forms.FormClosingEventHandler(Closing);
    }
    #endregion
    private System.Windows.Forms.Button button1;
    private System.Windows.Forms.ListBox listBox1;
    private System.Windows.Forms.Button button2;
  }
}
//Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.Net.Sockets;
using System.Collections;
namespace ServerTest
{
  public partial class Form1 : Form
  {
    int port = 2000;//綁定本機端口2000
    TcpListener listener;
    delegate void SetSafe(string text);
    ArrayList conList=new ArrayList();
    Encoding utf8 = Encoding.UTF8;
    Encoding gb2312 = Encoding.GetEncoding("GB2312");
    Thread listenerThread;
    Thread DataThread;
    public Form1()
    {
      InitializeComponent();
    }
    public void AcceptRequest() //連接處理線程
    {
      try
      {
        while (true)
        {
          if (listener.Pending())//是否有等待連接隊列
          {
            Socket s = listener.AcceptSocket();//建立連接
            conList.Add(s);//添加當前連接到已連接列表
            if (s.Connected)
            {
              string ServerEndPoint = "歡迎登陸服務器" + s.LocalEndPoint.ToString() + "\r\n";
              byte[] bgb = gb2312.GetBytes(ServerEndPoint);
              byte[] butf = Encoding.Convert(gb2312, utf8, bgb);
              s.Send(butf);//發送歡迎登陸信息
              string mpoint = s.RemoteEndPoint.ToString();
              AddList(mpoint);//把當前客戶端IP,Port添加到ListBox顯示
            }
          }
        }
      }
      catch { }
      Thread.Sleep(1000);
    }
    public void ReceiveData()//數據處理線程
    {
        while (true)
        {
          try
          {
            ArrayList CloseSocketList = new ArrayList();//關閉連接列表
            CloseSocketList.Clear();//清空關閉連接列表
            foreach (Socket s in conList)//循環每一個已建立的連接
            {
              NetworkStream ns = new NetworkStream(s);
              StreamReader reader = new StreamReader(ns);
              if (ns.DataAvailable)
              {
                string result = reader.ReadLine();
                byte[] u = utf8.GetBytes(result);
                byte[] gb = Encoding.Convert(utf8, gb2312, u);
                string sGb = gb2312.GetString(gb);
                if (sGb.StartsWith("Close"))//如果收到Close信息
                {
                  CloseSocketList.Add(s);//把當前連接添加到關閉連接列表
                }
                else
                {
                  foreach (Socket p in conList)//把從一個連接得到的信息發給所有的連接的客戶端,就好比聊天室的聊天大廳,公共聊天
                  {
                    string sendString = result + "\r\n";
                    byte[] butf = utf8.GetBytes(sendString);
                    p.Send(butf);
                  }
                }
              }
              reader.Close();
              ns.Close();
            }
            foreach (Socket s in CloseSocketList)//關閉關閉連接列表裡面的連接
            {
              DelList(s.RemoteEndPoint.ToString());//從ListBox刪除關閉的連接
              s.Close();
              conList.Remove(s);
            }
          }
          catch { }
          Thread.Sleep(1000);
        }
    }
    private void button1_Click(object sender, EventArgs e)//啟動服務器
    {
      listener = new TcpListener(port);//開啟2000端口的監聽
      listener.Start();
      listenerThread = new Thread(new ThreadStart(AcceptRequest));//啟動連接處理線程
      listenerThread.Start();
      DataThread = new Thread(new ThreadStart(ReceiveData));//啟動數據處理線程
      DataThread.Start();
    }
    private void AddList(object text)
    {
      // InvokeRequired required compares the thread ID of the
      // calling thread to the thread ID of the creating thread.
      // If these threads are different, it returns true.
      if (this.listBox1.InvokeRequired)
      {
        SetSafe d = new SetSafe(AddList);
        this.Invoke(d, new object[] { text });
      }
      else
      {
        this.listBox1.Items.Add(text);
      }
    }
    private void DelList(object text)
    {
      // InvokeRequired required compares the thread ID of the
      // calling thread to the thread ID of the creating thread.
      // If these threads are different, it returns true.
      if (this.listBox1.InvokeRequired)
      {
        SetSafe d = new SetSafe(DelList);
        this.Invoke(d, new object[] { text });
      }
      else
      {
        this.listBox1.Items.Remove(text);
      }
    }
    private void button2_Click(object sender, EventArgs e)//踢指定的客戶端連接
    {
      try
      {
        string temp = listBox1.SelectedItem.ToString();//選擇要踢的客戶端
        DelList(temp);//ListBox刪除它
        foreach (Socket f in conList)
        {
          if ((f.RemoteEndPoint.ToString()) == temp)//找到那個要踢的客戶端
          {
            string Message = "你被服務器T了" + "\r\n";
            byte[] bgb = gb2312.GetBytes(Message);
            byte[] butf = Encoding.Convert(gb2312, utf8, bgb);
            f.Send(butf);//告訴他他被踢了
            conList.Remove(f);//把它從已經連接列表中刪除,斷開連接
            f.Close();
          }
        }
      }
      catch { }
    }
    private void Closing(object sender, EventArgs e)//窗體關閉,斷開所有連接,關閉所有線程
    {
      try
      {
        foreach (Socket o in conList)
        {
          o.Close();
        }
        listenerThread.Abort();
        DataThread.Abort();
      }
      catch { }
    }
  }
}
這個例子比較簡單,實際在使用中會比較復雜,比如說我們的服務端要實現很多功能,舉個網絡游戲的例子,你要行走,要攻擊,要加血,要回藍,這每一個動作都對應一個命令,是以命令+內容+結束符的格式傳送給服務器的,服務器在接收到信息,再對信息分類處理。下面我看一個這樣的例子,是一個FTP的例子。客戶端可以顯示服務器的文件列表,可以選擇要下載的文件,可以上傳文件,服務器可以顯示客戶端的連接IP,可以斷開指定的客戶端。
客戶端
//Form1.Designer.Cs
namespace FTPClientTest
{
  partial class Form1
  {
    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;
    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
      if (disposing && (components != null))
      {
        components.Dispose();
      }
      base.Dispose(disposing);
    }
    #region Windows Form Designer generated code
    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
      this.listBox1 = new System.Windows.Forms.ListBox();
      this.button1 = new System.Windows.Forms.Button();
      this.button2 = new System.Windows.Forms.Button();
      this.button3 = new System.Windows.Forms.Button();
      this.button4 = new System.Windows.Forms.Button();
      this.button5 = new System.Windows.Forms.Button();
      this.SuspendLayout();
      //
      // listBox1
      //
      this.listBox1.FormattingEnabled = true;
      this.listBox1.ItemHeight = 12;
      this.listBox1.Location = new System.Drawing.Point(11, 9);
      this.listBox1.Name = "listBox1";
      this.listBox1.Size = new System.Drawing.Size(271, 160);
      this.listBox1.TabIndex = 0;
      //
      // button1
      //
      this

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved