C#編寫一個網遊客戶端的完整步驟

本過程是使用Virtual Studio 2019實現的,利用老師給出的框架進行的修改。

一、認識NetworkStream(網絡流)

1、NetworkStream的相關知識點

①NetworkStream隻能使用於具有TCP/IP協議之中,用於UDP中雖然不會報錯,但是會出現異常。

②NetworkStream是面向連接的。

③NetworkStream是利用流的形式進行傳輸信息。

2、NetworkStream常用的屬性和方法

屬性或方法 解釋
CanRead 流是否支持讀取,可以從流中讀取數據,返回為true
DataAvailable 看讀取的流上是否有可用的數據,常用來判斷流是否還有數據
Read(byte[] buffer,int offset,int size) 將數據讀入到buffer中,並返回成功讀取的字節數
Write(byte[] buffer,int offset,int size) 將buffer中的數據內容發送到網絡

瞭解NetworkStream,有助於幫助後面采用TcpClient進行數據收發,有興趣也可以瞭解一下StreamReader,StreamWriter。

二、連接服務器

代碼:

private NetworkStream stream;
private TcpClient tcpClient = new TcpClient();
public Form1()
{
      InitializeComponent();
      try
            {
                //向指定的IP地址的服務器發出連接請求
                tcpClient.Connect("10.160.52.106", 3900);
                listBox1.Items.Add("連接成功!");
                stream = tcpClient.GetStream();
                byte[] data = new byte[1024];
                //判斷網絡流是否可讀            
                if (stream.CanRead)
                {
                    int len = stream.Read(data, 0, data.Length);
                    //Encoding ToEncoding = Encoding.GetEncoding("UTF-8");
                    //Encoding FromEncoding = Encoding.GetEncoding("GB2312");
                    //data=Encoding.Convert(FromEncoding, ToEncoding, data);
                    //string msg = Encoding.UTF8.GetString(data, 0, data.Length);
                    string msg = Encoding.Default.GetString(data, 0, data.Length);
                    string str = "\r\n";
                    char[] str1 = str.ToCharArray();
                    string[] msg1=msg.Split(str1);
                    for(int j = 0; j < msg1.Length; j++)
                    {
                        listBox1.Items.Add(msg1[j]);
                    }
                }
            }
            catch
            {
                listBox1.Items.Add("服務器未啟動!");
            }
}

分析:

本過程是先為界面創建一個TCPClient對象屬性,在窗體初始化的時候,就連接服務器,並把服務器返回的數據在ListBox中顯示出來。由於一些轉義控制字符無法進行解析,返回的數據會出現一些特殊字符。

運行效果:

在顯示返回的數據時,最開始采用UTF-8編碼的時候,顯示回的數據是亂碼的情況。
解決方式:
①采用Default的方式
string msg = Encoding.Default.GetString(data, 0, data.Length);
②進行編碼轉換(GB轉換為UTF-8)
Encoding ToEncoding = Encoding.GetEncoding(“UTF-8”);
Encoding FromEncoding = Encoding.GetEncoding(“GB2312”);
data=Encoding.Convert(FromEncoding, ToEncoding, data);
string msg = Encoding.UTF8.GetString(data, 0, data.Length);
獲得的數據直接采用listBox的Add方法添加,顯示隻會顯示一行數據,不會進行換行
解決方式(對字符串以\r\n為分隔符進行分割,循環顯示)
string str = “\r\n”;
char[] str1 = str.ToCharArray();
string[] msg1=msg.Split(str1);
for(int j = 0; j < msg1.Length; j++)
{
listBox1.Items.Add(msg1[j]);
}

三、客戶端向服務器發送數據

代碼:

private void button12_Click(object sender, EventArgs e)
{
     //判斷連接是否斷開
     if (tcpClient.Connected)
     {
     	//向服務器發送數據
      	string msg = textBox1.Text;
        Byte[] outbytes = System.Text.Encoding.Default.GetBytes(msg+"\n");
        stream.Write(outbytes, 0, outbytes.Length);
        byte[] data = new byte[1024];
        //接收服務器回復數據
        if (stream.CanRead)
         {
         	int len = stream.Read(data, 0, data.Length);
            string msg1 = Encoding.Default.GetString(data, 0, data.Length);
            string str = "\r\n";
            char[] str1 = str.ToCharArray();
            string[] msg2 = msg1.Split(str1);
            for (int j = 0; j < msg2.Length; j++)
            {
            	listBox1.Items.Add(msg2[j]);
            }
         }
      }
      else
      {
       	listBox1.Items.Add("連接已斷開");
      }
}

分析:

將輸入到textBox中的信息發送給服務器,再將服務器發送回來的數據給添加到ListBox中顯示出來。

運行效果:

最開始發送數據的時候,服務器不返回任何數據
解決方式:
在發送的數據內容後面加上回車(\n),需要回車的原因是來表示客服端向服務器發送某個消息的結束標識。(僅是筆者的看法,並不準確)
每次在textBox輸入信息,都有先刪除上一次的內容,比較麻煩
解決方式:
在按鈕事件中添加textBox1.Clear()語句

四、實現播放背景音樂

添加WindowsMediaPlayer控件

沒有的情況下,添加控件的方法

選擇常規後,右鍵,再選擇選擇項,就會彈出一個新界面,在新界面上選擇COM組件。接下來就是找到所需要的控件,將其勾選上。

代碼:

private void button13_Click(object sender, EventArgs e)
{
      string s = @"D:\game1\game1\bin\Debug\Wav\mp3\Kapuskasing.mp3";
      axWindowsMediaPlayer1.URL = s;
}
private void button14_Click(object sender, EventArgs e)
{
       //用於暫停正在播放的背景音樂
       axWindowsMediaPlayer1.Ctlcontrols.pause();
}

分析:

播放和停止播放是通過兩個按鈕的點擊來實現的。當點擊播放按鈕後,就會播放背景音樂,需要暫停播放,就點擊停止按鈕就可以實現停止。

運行效果:


實際上,點擊播放按鈕後,存在背景音樂在播放。點擊停止時,就沒有瞭。

五、實現遊戲背景圖片變換

代碼:

int flag = 0;
private void timer1_Tick(object sender, EventArgs e)
{
      flag++;
      string picturePath = @"D:\game1\game1\bin\Debug\imag\"+flag+".jpg";
      pictureBox1.Image = Image.FromFile(picturePath);
      if (flag == 5)
      {
           flag = 0;
      }
}

分析:

該過程是利用Timer控件的tick事件來實現的,此處是利用Timer每隔3s會重新執行一次,然後pictureBox控件的圖片路徑就被修改。從而,實現圖片的變換。

運行效果:

timer的時間間隔的設置方式
在界面設計下,選中timer控件,接著在右邊的屬性區域中,找到Interval後,設置它的值,默認值為100(0.1s)。還需要將Enable的值修改為true。

六、小結

本過程主要是實現一個簡單網遊客戶端的部分功能實現。背景音樂與背景圖片的變換兩種功能。這個功能的實現方式並不是隻有我展示,還有其他的方式。整個過程還是花瞭比較久的時間,主要是對於一些控件使用不是很熟悉。界面的設計部分是使用的老師發的框架代碼,有些控件的時間功能還沒有實現。最開始在服務器的連接上,並沒有成功,應該是對應的服務器端有問題。在連接服務器成功後,就數據的收發問題上,還是花瞭比較多的時間。起初,接受的的數據存在一些亂碼的情況,就一直不明白是怎麼回事。最後,才知道是編碼上的問題和一些轉義控制字符沒有辦法轉義得到正確的顯示。采用循環的時候,沒有報錯之類的問題出現,可點擊運行,就是沒有界面彈出,去掉循環部分,卻又有界面出現,就不知道是什麼情況。在網上查看資料,也沒有發現是什麼問題。最後,不知道怎麼回事,運行又可以瞭。

七、參考資料

  • Socket編程—TcpListener和TcpClient的使用
  • C#winform怎樣設計定時更換圖片
  • AxWindowsMediaPlayer控件的屬性
  • visual studio2010中C#怎麼播放MP3背景音樂
  • C# Stream篇(七) – NetworkStream

總結

到此這篇關於C#編寫一個網遊客戶端的文章就介紹到這瞭,更多相關C#編寫網遊客戶端內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: