C#編寫一個網(wǎng)游客戶端的完整步驟
本過程是使用Virtual Studio 2019實(shí)現(xiàn)的,利用老師給出的框架進(jìn)行的修改。
一、認(rèn)識NetworkStream(網(wǎng)絡(luò)流)
1、NetworkStream的相關(guān)知識點(diǎn)
①NetworkStream只能使用于具有TCP/IP協(xié)議之中,用于UDP中雖然不會報錯,但是會出現(xiàn)異常。
②NetworkStream是面向連接的。
③NetworkStream是利用流的形式進(jìn)行傳輸信息。
2、NetworkStream常用的屬性和方法
屬性或方法 | 解釋 |
---|---|
CanRead | 流是否支持讀取,可以從流中讀取數(shù)據(jù),返回為true |
DataAvailable | 看讀取的流上是否有可用的數(shù)據(jù),常用來判斷流是否還有數(shù)據(jù) |
Read(byte[] buffer,int offset,int size) | 將數(shù)據(jù)讀入到buffer中,并返回成功讀取的字節(jié)數(shù) |
Write(byte[] buffer,int offset,int size) | 將buffer中的數(shù)據(jù)內(nèi)容發(fā)送到網(wǎng)絡(luò) |
了解NetworkStream,有助于幫助后面采用TcpClient進(jìn)行數(shù)據(jù)收發(fā),有興趣也可以了解一下StreamReader,StreamWriter。
二、連接服務(wù)器
代碼:
private NetworkStream stream; private TcpClient tcpClient = new TcpClient(); public Form1() { InitializeComponent(); try { //向指定的IP地址的服務(wù)器發(fā)出連接請求 tcpClient.Connect("10.160.52.106", 3900); listBox1.Items.Add("連接成功!"); stream = tcpClient.GetStream(); byte[] data = new byte[1024]; //判斷網(wǎng)絡(luò)流是否可讀 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("服務(wù)器未啟動!"); } }
分析:
本過程是先為界面創(chuàng)建一個TCPClient對象屬性,在窗體初始化的時候,就連接服務(wù)器,并把服務(wù)器返回的數(shù)據(jù)在ListBox中顯示出來。由于一些轉(zhuǎn)義控制字符無法進(jìn)行解析,返回的數(shù)據(jù)會出現(xiàn)一些特殊字符。
運(yùn)行效果:
在顯示返回的數(shù)據(jù)時,最開始采用UTF-8編碼的時候,顯示回的數(shù)據(jù)是亂碼的情況。
解決方式:
①采用Default的方式
string msg = Encoding.Default.GetString(data, 0, data.Length);
②進(jìn)行編碼轉(zhuǎn)換(GB轉(zhuǎn)換為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);
獲得的數(shù)據(jù)直接采用listBox的Add方法添加,顯示只會顯示一行數(shù)據(jù),不會進(jìn)行換行
解決方式(對字符串以\r\n為分隔符進(jìn)行分割,循環(huá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]);
}
三、客戶端向服務(wù)器發(fā)送數(shù)據(jù)
代碼:
private void button12_Click(object sender, EventArgs e) { //判斷連接是否斷開 if (tcpClient.Connected) { //向服務(wù)器發(fā)送數(shù)據(jù) string msg = textBox1.Text; Byte[] outbytes = System.Text.Encoding.Default.GetBytes(msg+"\n"); stream.Write(outbytes, 0, outbytes.Length); byte[] data = new byte[1024]; //接收服務(wù)器回復(fù)數(shù)據(jù) 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中的信息發(fā)送給服務(wù)器,再將服務(wù)器發(fā)送回來的數(shù)據(jù)給添加到ListBox中顯示出來。
運(yùn)行效果:
最開始發(fā)送數(shù)據(jù)的時候,服務(wù)器不返回任何數(shù)據(jù)
解決方式:
在發(fā)送的數(shù)據(jù)內(nèi)容后面加上回車(\n),需要回車的原因是來表示客服端向服務(wù)器發(fā)送某個消息的結(jié)束標(biāo)識。(僅是筆者的看法,并不準(zhǔn)確)
每次在textBox輸入信息,都有先刪除上一次的內(nèi)容,比較麻煩
解決方式:
在按鈕事件中添加textBox1.Clear()語句
四、實(shí)現(xiàn)播放背景音樂
添加WindowsMediaPlayer控件
沒有的情況下,添加控件的方法
選擇常規(guī)后,右鍵,再選擇選擇項(xiàng),就會彈出一個新界面,在新界面上選擇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(); }
分析:
播放和停止播放是通過兩個按鈕的點(diǎn)擊來實(shí)現(xiàn)的。當(dāng)點(diǎn)擊播放按鈕后,就會播放背景音樂,需要暫停播放,就點(diǎn)擊停止按鈕就可以實(shí)現(xiàn)停止。
運(yùn)行效果:
實(shí)際上,點(diǎn)擊播放按鈕后,存在背景音樂在播放。點(diǎn)擊停止時,就沒有了。
五、實(shí)現(xiàn)游戲背景圖片變換
代碼:
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事件來實(shí)現(xiàn)的,此處是利用Timer每隔3s會重新執(zhí)行一次,然后pictureBox控件的圖片路徑就被修改。從而,實(shí)現(xiàn)圖片的變換。
運(yùn)行效果:
timer的時間間隔的設(shè)置方式
在界面設(shè)計下,選中timer控件,接著在右邊的屬性區(qū)域中,找到Interval后,設(shè)置它的值,默認(rèn)值為100(0.1s)。還需要將Enable的值修改為true。
六、小結(jié)
本過程主要是實(shí)現(xiàn)一個簡單網(wǎng)游客戶端的部分功能實(shí)現(xiàn)。背景音樂與背景圖片的變換兩種功能。這個功能的實(shí)現(xiàn)方式并不是只有我展示,還有其他的方式。整個過程還是花了比較久的時間,主要是對于一些控件使用不是很熟悉。界面的設(shè)計部分是使用的老師發(fā)的框架代碼,有些控件的時間功能還沒有實(shí)現(xiàn)。最開始在服務(wù)器的連接上,并沒有成功,應(yīng)該是對應(yīng)的服務(wù)器端有問題。在連接服務(wù)器成功后,就數(shù)據(jù)的收發(fā)問題上,還是花了比較多的時間。起初,接受的的數(shù)據(jù)存在一些亂碼的情況,就一直不明白是怎么回事。最后,才知道是編碼上的問題和一些轉(zhuǎn)義控制字符沒有辦法轉(zhuǎn)義得到正確的顯示。采用循環(huán)的時候,沒有報錯之類的問題出現(xiàn),可點(diǎn)擊運(yùn)行,就是沒有界面彈出,去掉循環(huán)部分,卻又有界面出現(xiàn),就不知道是什么情況。在網(wǎng)上查看資料,也沒有發(fā)現(xiàn)是什么問題。最后,不知道怎么回事,運(yùn)行又可以了。
七、參考資料
- Socket編程—TcpListener和TcpClient的使用
- C#winform怎樣設(shè)計定時更換圖片
- AxWindowsMediaPlayer控件的屬性
- visual studio2010中C#怎么播放MP3背景音樂
- C# Stream篇(七) – NetworkStream
總結(jié)
到此這篇關(guān)于C#編寫一個網(wǎng)游客戶端的文章就介紹到這了,更多相關(guān)C#編寫網(wǎng)游客戶端內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C# 使用SDL2實(shí)現(xiàn)Mp4文件播放音視頻操作
這篇文章主要介紹了C# 使用SDL2實(shí)現(xiàn)Mp4文件播放音視頻操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12