版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、第8章 MyQQ的設(shè)計(jì)8.1 項(xiàng)目的創(chuàng)建8.2 數(shù)據(jù)包的設(shè)計(jì)8.3 主界面的設(shè)計(jì)8.4 聊天窗口的設(shè)計(jì)8.5 讀者完成部分第1頁(yè),共76頁(yè)。知識(shí)點(diǎn)鏈接L8.1 項(xiàng)目的創(chuàng)建L8.3 主界面的設(shè)計(jì)L8.5 讀者完成部分第2頁(yè),共76頁(yè)。1. MyQQ的介紹當(dāng)雙擊所要聊天對(duì)象時(shí)彈出聊天窗口,聊天窗口如圖8.2所示,用于發(fā)送信息和顯示聊天信息。 圖8.1 MyQQ主界面 圖8.2 聊天窗口第3頁(yè),共76頁(yè)。2所要掌握的主要知識(shí)點(diǎn)(1)網(wǎng)絡(luò)通信知識(shí)點(diǎn),Socket、TcpListener、TcpClient和UdpClient類。(2)線程知識(shí)點(diǎn),Thread類。(3)熟悉ListView控件、Noti
2、fyIcon組件的使用。第4頁(yè),共76頁(yè)。8.1 項(xiàng)目的創(chuàng)建MyQQ應(yīng)用程序主要講述網(wǎng)絡(luò)通信和多線程,包括主界面窗體和聊天窗口窗體這兩個(gè)窗體,主界面主要顯示在線的人物以及選擇聊天對(duì)象,聊天窗口用于發(fā)送聊天信息和接受聊天信息。此項(xiàng)目中同時(shí)還包括封裝數(shù)據(jù)包的類DataPacket。項(xiàng)目的創(chuàng)建步驟:1創(chuàng)建項(xiàng)目運(yùn)行VS2008,執(zhí)行【文件】【新建】【項(xiàng)目】命令,在彈出的“新建項(xiàng)目”對(duì)話框中選中“Windows窗體應(yīng)用程序”模板,選擇項(xiàng)目存放位置并輸入項(xiàng)目名稱為“MyQQ”,單擊“確定”按鈕完成項(xiàng)目的創(chuàng)建。2添加窗體打開(kāi)“解決方案資源管理器”窗口,右擊項(xiàng)目名“MyQQ”,依次執(zhí)行快捷菜單中的“添加”“新
3、建項(xiàng)”命令,在彈出的“添加新項(xiàng)”對(duì)話框中選中“Windows窗體”模板,使用默認(rèn)名稱“Form1”,單擊“添加”按鈕完成窗體的添加。按照同樣的方法再添加一個(gè)窗體,使用默認(rèn)命名。其中“Form1”為主界面窗體,“Form2”為聊天窗口窗體。第5頁(yè),共76頁(yè)。8.1 項(xiàng)目的創(chuàng)建3添加類DataPacket在“解決方案資源管理器”窗口中,右擊項(xiàng)目名“MyQQ”,依次執(zhí)行快捷菜單中的“添加”“新建項(xiàng)”命令,在彈出的“添加新項(xiàng)”對(duì)話框中選中“類”模板,命名為“DataPacket.cs”并單擊“添加”按鈕。到此完成了整個(gè)項(xiàng)目的創(chuàng)建。第6頁(yè),共76頁(yè)。8.2 數(shù)據(jù)包的設(shè)計(jì)數(shù)據(jù)包格式包括“命令號(hào)”、“發(fā)送端
4、IP”、“用戶名長(zhǎng)度”、“用戶名”、“接受端IP”和“內(nèi)容”6個(gè)部分。命令號(hào)是說(shuō)明此數(shù)據(jù)包用于所要執(zhí)行的任務(wù),發(fā)送端IP是指發(fā)送信息端的IP地址,用戶名為發(fā)送端的用戶名,用戶名的字節(jié)數(shù)是指發(fā)送端的用戶名的字節(jié)數(shù),接受端IP是指所要發(fā)送到對(duì)方的IP地址,內(nèi)容是指數(shù)據(jù)包所附帶的信息。數(shù)據(jù)包的結(jié)構(gòu)如圖8.3所示。圖8.3 數(shù)據(jù)包結(jié)構(gòu)第7頁(yè),共76頁(yè)。8.2 數(shù)據(jù)包的設(shè)計(jì)設(shè)計(jì)步驟:1. 添加命名空間打開(kāi)類DataPacket,因?yàn)榇祟愔猩婕熬W(wǎng)絡(luò),所以要添加如下命名空間:using System.Net;2. 添加其他代碼代碼如下。第8頁(yè),共76頁(yè)。8.3 主界面的設(shè)計(jì)主界面窗體運(yùn)行后如圖8.1所示,通
5、過(guò)ListView控件和ImageList顯示在線的人物以及選擇聊天對(duì)象,通過(guò)StatusStrip控件顯示在線人數(shù)以及包括“上線”和“下線”功能。設(shè)計(jì)步驟:1. 添加控件和組件在解決方案資源管理器中打開(kāi)“Form1.cs”。將Form1窗體調(diào)整到適當(dāng)大小,從工具箱中拖放1個(gè)“NotifyIcon”組件、1個(gè)“ListView”和1個(gè)“ImageList”控件到此窗體中。參考圖8.1所示擺放控件。第9頁(yè),共76頁(yè)。8.3 主界面的設(shè)計(jì)2. 設(shè)置窗體和控件組件的屬性Form1的Text屬性值設(shè)置為“MyQQ”,Icon設(shè)置為已經(jīng)準(zhǔn)備好的圖標(biāo),MaximizeBox設(shè)置為“False”。(1)no
6、tifyIcon1的屬性設(shè)置。Icon選擇已經(jīng)準(zhǔn)備好的圖標(biāo),Text設(shè)置為“MyQQ”。(2)imageList1的屬性設(shè)置。在其屬性窗口中打開(kāi)“ ”按鈕圖標(biāo),彈出“圖像集合編輯器”窗口,分別添加一些用于顯示聊天對(duì)象的圖標(biāo),如圖8.4所示。圖8.4 圖像集合編輯器第10頁(yè),共76頁(yè)。8.3 主界面的設(shè)計(jì)(3)listView1的屬性設(shè)置。打開(kāi)listView1屬性窗口,F(xiàn)ullRowSelect和View屬性值分別設(shè)置為“True”和“Title”,MultiSelect設(shè)置為“False”,StateImageList屬性選擇為“imageList1”,Columns集合中分別添加3個(gè)“co
7、lumnHeader”成員。(4)statusStrip1的設(shè)置。分別添加一個(gè)“toolStripStatusLabel”和一個(gè)“toolStripDropDownButton”。toolStripStatusLabel1的Text屬性設(shè)置為“在線人數(shù) 人”,選中toolStripDropDownButton1Text,分別添加“上線”和“下線”選項(xiàng),如圖8.5所示,Image選擇準(zhǔn)備好的圖標(biāo)。圖8.5 添加上下線第11頁(yè),共76頁(yè)。8.3 主界面的設(shè)計(jì)3. 添加事件及代碼主窗口窗體包含有“窗體加載”、“上線”、“下線”、“選擇聊天對(duì)象”和“調(diào)整大小”事件。(1)添加命名空間。因?yàn)樯婕熬€程和網(wǎng)
8、絡(luò)的操作,所以添加命名空間如下:using System.Threading;using System.Net;using System.Net.Sockets;(2)添加字段。所添加的字段如下所示:private UdpClient UdpListen = new UdpClient(8000);private IPAddress myIP = Dns.GetHostEntry(Dns.GetHostName().AddressList0;/本機(jī)器IP地址private string myName = Environment.UserName; /本機(jī)器用戶名/*標(biāo)識(shí)網(wǎng)絡(luò)地址,初始化廣播端口
9、號(hào)*/private IPEndPoint EndPoint = new IPEndPoint(IPAddress.Parse(55), 8000);private static bool MyState = false;/是否為在線狀態(tài)第12頁(yè),共76頁(yè)。8.3 主界面的設(shè)計(jì)(3)主界面中添加上線人的成員方法。通過(guò)數(shù)據(jù)包參數(shù)將此上線的人的用戶名、IP地址以及圖像顯示在主界面中,并更新在線人數(shù)。代碼如下:private void AddPerson(DataPacket dp) /添加聊天的人 ListViewItem lviUserName = new ListViewItem(); Lis
10、tViewItem.ListViewSubItem lvsiComputerName = new ListViewItem.ListViewSubItem(); ListViewItem.ListViewSubItem lvsiIP = new ListViewItem.ListViewSubItem(); lvsiComputerName.Text = dp.ComputerName; lvsiIP.Text = dp.FromIP.ToString(); int imagecount = listView1.Items.Count % imageList1.Images.Count; /選
11、擇圖像 lviUserName.StateImageIndex = imagecount; lviUserName.SubItems.Add(lvsiComputerName); lviUserName.SubItems.Add(lvsiIP); listView1.Items.Add(lviUserName); toolStripStatusLabel1.Text = 在線人數(shù): + listView1.Items.Count + 人;/顯示聊天人數(shù)第13頁(yè),共76頁(yè)。8.3 主界面的設(shè)計(jì)(4)監(jiān)聽(tīng)指定端口的廣播地址UDP包的成員方法的代碼。當(dāng)接受到數(shù)據(jù)包時(shí),分析其包的命令,并執(zhí)行相應(yīng)的代碼
12、。代碼如下所示。(5)添加“窗體加載”事件及其代碼。當(dāng)窗體加載時(shí)就開(kāi)啟監(jiān)聽(tīng)線程,切換到Form1的設(shè)計(jì)視圖,雙擊窗體,添加代碼,代碼如下所示:private void Form1_Load(object sender, EventArgs e) /*開(kāi)啟監(jiān)聽(tīng)線程*/ Thread myThread = new Thread(new ThreadStart(this.ListenPort); myThread.IsBackground = true; myThread.Start(); Control.CheckForIllegalCrossThreadCalls = false;/忽略跨線程錯(cuò)
13、誤,這時(shí)會(huì)拋出異常第14頁(yè),共76頁(yè)。8.3 主界面的設(shè)計(jì)(6)添加上下線事件及其代碼。當(dāng)單擊“上線”和“下線”時(shí)分別發(fā)送“上線”和“下線”數(shù)據(jù)包。切換到設(shè)計(jì)視圖并分別雙擊“上線”和“下線”,添加事件代碼,代碼如下。第15頁(yè),共76頁(yè)。8.3 主界面的設(shè)計(jì)(7)添加選中聊天對(duì)象事件及其代碼。當(dāng)雙擊聊天對(duì)象時(shí)彈出聊天窗口并發(fā)生聊天請(qǐng)求數(shù)據(jù)包。在listView1的事件窗口中雙擊DoubleClick,添加其事件代碼,代碼如下:private void listView1_DoubleClick(object sender, EventArgs e)/聊天 string strChatIP = l
14、istView1.SelectedItems0.SubItems2.Text; IPAddress IPAddChatIP = IPAddress.Parse(strChatIP); Form2 form2 = new Form2(myIP, myName, IPAddChatIP); form2.Show(); /*發(fā)送聊天請(qǐng)求數(shù)據(jù)包*/ DataPacket comeDataPacket = new DataPacket(); comeDataPacket.CommandNo = 1; comeDataPacket.FromIP = myIP; comeDataPacket.NameLen
15、gth = myName.Length; comeDataPacket.ComputerName = myName; comeDataPacket.ToIP = IPAddChatIP; comeDataPacket.Content = 聊天請(qǐng)求; byte sendb = comeDataPacket.PacketToBytes(); UdpListen.Send(sendb, sendb.Length, EndPoint);/發(fā)送信息第16頁(yè),共76頁(yè)。8.3 主界面的設(shè)計(jì)(8)添加關(guān)閉窗口事件及其代碼。當(dāng)關(guān)閉窗口退出程序時(shí)發(fā)送下線數(shù)據(jù)包。打開(kāi)Form1的事件窗口,雙擊“FormClose
16、d”,添加其事件代碼,代碼如下:private void Form1_FormClosed(object sender, FormClosedEventArgs e)/關(guān)閉窗口 下線ToolStripMenuItem_Click(null, null);/下線(9)添加調(diào)整大小事件。當(dāng)最小化主界面時(shí),最小化到任務(wù)欄狀態(tài)通知區(qū)域中。打開(kāi)Form1的事件窗口,雙擊“Resize”,添加其事件代碼,代碼如下:private void Form1_Resize(object sender, EventArgs e) if (this.WindowState = FormWindowState.Mini
17、mized) this.Visible = false; /隱藏窗體 this.notifyIcon1.Visible = true; /在托盤中顯示圖標(biāo) 第17頁(yè),共76頁(yè)。8.3 主界面的設(shè)計(jì)(10)添加notifyIcon1的雙擊事件。打開(kāi)notifyIcon1的事件窗口,雙擊“DoubleClick”,添加其事件代碼,代碼如下:private void notifyIcon1_DoubleClick(object sender, EventArgs e) this.Visible = true;/顯示主窗口 this.WindowState = FormWindowState.Norm
18、al; this.notifyIcon1.Visible = false; 第18頁(yè),共76頁(yè)。8.3 主界面的設(shè)計(jì)4. 運(yùn)行程序按【Ctrl+F5】組合鍵運(yùn)行程序。選擇上線選項(xiàng),則自己的圖標(biāo)、用戶名和IP地址顯示在主界面中。當(dāng)最小化MyQQ時(shí),進(jìn)程圖標(biāo)顯示在任務(wù)欄狀態(tài)通知區(qū)域中。如圖8.6所示。圖8.6 MyQQ進(jìn)程圖標(biāo)第19頁(yè),共76頁(yè)。8.4 聊天窗口的設(shè)計(jì)聊天窗口用于發(fā)送聊天信息給聊天對(duì)象并接受聊天對(duì)象的信息。在這里為了突出知識(shí)點(diǎn)和教學(xué)方便,使用傳輸控制協(xié)議 (TCP)只實(shí)現(xiàn)發(fā)送信息給自己并接受信息。運(yùn)行的界面如圖8.2所示。設(shè)計(jì)步驟:1. 添加控件在解決方案資源管理器中打開(kāi)“Form
19、2.cs”。將Form2窗體調(diào)整到適當(dāng)大小,從工具箱中拖放1個(gè)“toolStrip1”、2個(gè)“TextBox”和2個(gè)“Button”控件到此窗體中。參考圖8.2所示擺放控件。2. 窗體和控件屬性設(shè)置打開(kāi)Form2的屬性窗口,Text屬性設(shè)置為“MyQQ”,MaximizeBox、MinimizeBox和ShowIcon的屬性值都設(shè)置為“False”。StartPosition屬性值設(shè)置為“CenterScreen”。button1和button2的Text屬性值設(shè)置為“發(fā)送”和“關(guān)閉”。toolStrip1學(xué)生可以自己設(shè)計(jì)。第20頁(yè),共76頁(yè)。8.4 聊天窗口的設(shè)計(jì)3. 添加事件及代碼聊天窗口
20、包含有“發(fā)送”和“關(guān)閉”事件。(1)添加命名空間。因?yàn)樯婕熬€程、文件系統(tǒng)和網(wǎng)絡(luò)的操作,所以添加命名空間如下:using System.Net.Sockets;using System.Net;using System.IO;using System.Threading;(2)添加字段。所添加的字段如下所示:IPAddress myIP;/發(fā)送方的IP地址IPAddress toIP;/接受方的IP地址string myName;/方式方的用戶名TcpListener tcpListener; /接受方用于TCP監(jiān)聽(tīng)TcpClient tcpClient;/發(fā)送方用于請(qǐng)求與對(duì)方連接Socket
21、socket;Thread receThread;/發(fā)送信息線程第21頁(yè),共76頁(yè)。8.4 聊天窗口的設(shè)計(jì)(3)添加構(gòu)造函數(shù)。此構(gòu)造函數(shù)用于接收從主界面?zhèn)鬟^(guò)來(lái)的發(fā)送方的IP地址,發(fā)送方的用戶名以及接受方的IP地址。代碼如下:public Form2(IPAddress myip,string myname,IPAddress toip) InitializeComponent(); myIP = myip; toIP = toip; myName = myname;第22頁(yè),共76頁(yè)。8.4 聊天窗口的設(shè)計(jì)(4)添加監(jiān)聽(tīng)端口并接受信息成員方法。監(jiān)聽(tīng)3333端口并將接受到的信息轉(zhuǎn)換為字符串類型并
22、顯示在textBox1中,代碼如下:private void receiveData() tcpListener = new TcpListener(IPAddress.Any, 3333);/新建TcpListener對(duì)象 while (true) tcpListener.Start(); /開(kāi)始監(jiān)聽(tīng)端口 socket = tcpListener.AcceptSocket();/接受連接請(qǐng)求 byte buffter = new byte1024; /定義緩沖區(qū) while (socket.Receive(buffter) != 0)/接受消息 textBox1.Text += Encodi
23、ng.Default.GetString(buffter); /轉(zhuǎn)換為字符串并顯示 socket.Close();/關(guān)閉連接 tcpListener.Stop();/停止監(jiān)聽(tīng) 第23頁(yè),共76頁(yè)。8.4 聊天窗口的設(shè)計(jì)(5)添加窗體加載事件及其代碼。當(dāng)窗體加載時(shí)新建一個(gè)線程用于監(jiān)聽(tīng)端口并接受消息。切換到設(shè)計(jì)視圖,雙擊Form2,添加其事件代碼,代碼如下:private void Form2_Load(object sender, EventArgs e) receThread = new Thread(new ThreadStart(receiveData); /新建一個(gè)線程用于監(jiān)聽(tīng)消息 re
24、ceThread.Start(); 第24頁(yè),共76頁(yè)。8.4 聊天窗口的設(shè)計(jì)(6)添加“發(fā)送”按鈕事件及其事件代碼?!鞍l(fā)送”按鈕用于和對(duì)方建立連接并將信息發(fā)送給對(duì)方。雙擊“發(fā)送”按鈕,其事件代碼如下:private void button1_Click(object sender, EventArgs e) tcpClient = new TcpClient(); tcpClient.Connect(toIP, 3333);/建立連接 NetworkStream stream = tcpClient.GetStream();/獲取網(wǎng)絡(luò)流 string strsent = myName + (
25、 + myIP.ToString() + ) + DateTime.Now.ToString() + rn + textBox2.Text+rn;/顯示發(fā)送者和發(fā)送時(shí)間 byte buftter = Encoding.Default.GetBytes(strsent);/將要發(fā)送的文本轉(zhuǎn)換為字節(jié)流 stream.Write(buftter, 0, buftter.Length);/寫入網(wǎng)絡(luò)流中 stream.Close(); /關(guān)閉網(wǎng)絡(luò)流 tcpClient.Close();/關(guān)閉連接第25頁(yè),共76頁(yè)。8.4 聊天窗口的設(shè)計(jì)(7)添加“關(guān)閉”按鈕事件及其事件代碼?!瓣P(guān)閉”按鈕用于結(jié)束線程和關(guān)
26、閉窗體等。雙擊“關(guān)閉”按鈕,其事件代碼如下:private void button2_Click(object sender, EventArgs e) receThread.Abort();/結(jié)束線程 if (tcpListener != null) tcpListener.Stop();/停止監(jiān)聽(tīng) this.Close();/關(guān)閉窗體第26頁(yè),共76頁(yè)。8.4 聊天窗口的設(shè)計(jì)4. 運(yùn)行程序按【Ctrl+F5】組合鍵運(yùn)行程序。選擇“上線”選項(xiàng),雙擊自己圖標(biāo),在彈出的聊天窗口中發(fā)送信息,運(yùn)行的結(jié)果如圖8.2所示。第27頁(yè),共76頁(yè)。8.5 讀者完成部分考慮到篇幅和知識(shí)點(diǎn)等因素,以上介紹完成的M
27、yQQ不是很完善并有一些缺陷。讀者可將此MyQQ加以修改并完善。(1)在此實(shí)例中沒(méi)有應(yīng)用數(shù)據(jù)包內(nèi)容部分,改寫程序?qū)⑺l(fā)送的聊天信息加載到數(shù)據(jù)包的內(nèi)容部分并通過(guò)UDP服務(wù)方式來(lái)發(fā)送和接受聊天信息。(2)利用TCP方式在聊天窗口中添加文件傳輸功能。(3)添加聊天記錄功能,將所有聊天信息記錄下來(lái)并在聊天窗口添加讀取聊天記錄功能。(4)刪除“主界面設(shè)計(jì)”中的“Control.CheckForIllegalCrossThreadCalls = false;”代碼,使用線程間通信完成。第28頁(yè),共76頁(yè)。L8.1 項(xiàng)目的創(chuàng)建L1. 網(wǎng)絡(luò)通信(1)同步方式同步方式是指發(fā)送方發(fā)送數(shù)據(jù)包以后,不等接收方響應(yīng),就
28、接著發(fā)送下一個(gè)數(shù)據(jù)包。(2)異步方式異步方式是指當(dāng)發(fā)送方發(fā)送一個(gè)數(shù)據(jù)包以后,一直等到接收方響應(yīng)后,才可以發(fā)送下一個(gè)數(shù)據(jù)包。(3)阻塞套接字阻塞套接字是指在執(zhí)行此套接字的網(wǎng)絡(luò)調(diào)用時(shí),直到調(diào)用成功才返回,否則此套接字就一直阻塞在網(wǎng)絡(luò)調(diào)用上。(4)非阻塞套接字非阻塞套接字是指在執(zhí)行此套接字的網(wǎng)絡(luò)調(diào)用時(shí),不管是否執(zhí)行成功,都立即返回。第29頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信1. Dns類IP地址是一種普遍應(yīng)用于因特網(wǎng)、允許不同主機(jī)能夠相互找到對(duì)方的尋址協(xié)議。IP地址由4個(gè)十進(jìn)制的數(shù)字號(hào)碼所組成,而每一個(gè)號(hào)碼的值為0255,這雖然解決了網(wǎng)絡(luò)上計(jì)算機(jī)的識(shí)別問(wèn)題,但是IP地址不易記憶,因此域名系統(tǒng)(DNS)被開(kāi)
29、發(fā)出來(lái),它專門用于將IP地址轉(zhuǎn)換成有意義的文字,以方便識(shí)別記憶。Dns 類是一個(gè)靜態(tài)類,它從 Internet 域名系統(tǒng) (DNS) 檢索關(guān)于特定主機(jī)的信息。在IPHostEntry 類的實(shí)例中返回來(lái)自 DNS 查詢的主機(jī)信息。如果指定的主機(jī)在 DNS 數(shù)據(jù)庫(kù)中有多個(gè)入口,則IPHostEntry 包含多個(gè) IP 地址和別名。Dns類常用方法及說(shuō)明如表8.1所示。第30頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信【例EX8_1】 設(shè)計(jì)WinForm應(yīng)用程序用于獲取指定主機(jī)名的IP地址。 設(shè)計(jì)步驟:(1)新建WinForm項(xiàng)目新建WinForm項(xiàng)目并命名為“EX8_1”。(2)添加控件并設(shè)置屬性在Form1的
30、設(shè)計(jì)視圖中,將此窗體調(diào)整到適當(dāng)?shù)拇笮〔?“Text”屬性設(shè)為“獲取主機(jī)IP地址”。從工具箱中拖放1個(gè)Button、2個(gè)Label和2個(gè)TextBox控件到窗體中,按如圖8.7所示方式布局控件。label1、label2和button1的Text屬性值分別設(shè)置為“主機(jī)名”、“IP地址:”和“獲取”。(3)添加命名空間所要添加的命名空間為“using System.Net;”。第31頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信(4)添加事件及代碼雙擊“獲取”按鈕,其事件代碼如下所示:private void button1_Click(object sender, EventArgs e) textBox2.
31、Text = ; try IPHostEntry hostInfo = Dns.GetHostEntry(textBox1.Text.Trim(); foreach (IPAddress ipadd in hostInfo.AddressList) textBox2.Text += ipadd.ToString() + rn; catch (Exception ex) MessageBox.Show(ex.Message.ToString(); 第32頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信(5)運(yùn)行程序按【Ctrl+F5】組合鍵運(yùn)行程序,分別輸入“”和“”,單擊“獲取”按鈕結(jié)果如圖8.7和圖8.8所示
32、。圖8.7 “”的IP地址圖8.8 “”的IP地址第33頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信2. System.Net.Sockets命名空間System.Net.Sockets 命名空間為需要嚴(yán)密控制網(wǎng)絡(luò)訪問(wèn)的開(kāi)發(fā)人員提供了 Windows Sockets (Winsock) 接口的托管實(shí)現(xiàn)。其中Socket類、TcpClient類、TcpListener類、UdpClinet類和NetWorkStrean類較為常用,下面對(duì)它們進(jìn)行簡(jiǎn)單介紹。(1)Socket類:用于管理連接,實(shí)現(xiàn)Berkeley通信端接口,定義綁定、連接網(wǎng)絡(luò)端點(diǎn)以及傳輸數(shù)據(jù)所需的方法,提供處理端點(diǎn)連接傳輸?shù)燃?xì)節(jié)所需要的功能。We
33、bRequest、TcpClient和UdpClinet等類在內(nèi)部使用這個(gè)類。(2)TcpClient類:允許創(chuàng)建和使用TCP連接,該類創(chuàng)建于Socket類的基礎(chǔ)之上并且封裝了許多更高級(jí)的功能,避免開(kāi)發(fā)人員處理連接操作的相關(guān)細(xì)節(jié)。(3)TcpListener類:允許監(jiān)聽(tīng)傳入的TCP連接請(qǐng)求,傾聽(tīng)來(lái)自TCP客戶端應(yīng)用程序的連接要求,封裝更高級(jí)的功能,使用這個(gè)類可以讓用戶避免處理一些連接服務(wù)的細(xì)節(jié),以一種比較有效的方式,接收傾聽(tīng)的連接需求。(4)UdpClinet類:提供用戶數(shù)據(jù)報(bào) (UDP) 網(wǎng)絡(luò)服務(wù)。 (5)NetWorkStream類:這個(gè)類是從Stream派生出來(lái)的,專門用以處理網(wǎng)絡(luò)形式的
34、數(shù)據(jù)流,與其他文件數(shù)據(jù)流的顯著區(qū)別在于,這個(gè)類接收Socket類對(duì)象參數(shù),對(duì)網(wǎng)絡(luò)數(shù)據(jù)進(jìn)行存取操作。第34頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信3. 套接字(Socket)區(qū)分不同應(yīng)用程序進(jìn)程間的網(wǎng)絡(luò)通信和連接,主要有3個(gè)參數(shù):通信的目的IP地址、使用的傳輸層協(xié)議(TCP或UDP)和使用的端口號(hào)。Socket原意是“插座”。通過(guò)將這3個(gè)參數(shù)結(jié)合起來(lái),與一個(gè)“插座”Socket綁定,應(yīng)用層就可以和傳輸層通過(guò)套接字接口,區(qū)分來(lái)自不同應(yīng)用程序進(jìn)程或網(wǎng)絡(luò)連接的通信,實(shí)現(xiàn)數(shù)據(jù)傳輸?shù)牟l(fā)服務(wù)。.NET Framework中的Socket類是Winsock32 API提供的套接字服務(wù)的托管代碼版本。在大多數(shù)情況下,S
35、ocket類方法只是將數(shù)據(jù)封送到它們的本機(jī)Win32副本中,并處理任何必要的安全檢查。Socket類支持兩種基本模式:同步和異步。在同步模式中,對(duì)執(zhí)行網(wǎng)絡(luò)操作的函數(shù)(如Send和Receive)的調(diào)用一直等到操作完成后才將控制權(quán)返回給調(diào)用程序,而在異步模式中,這些調(diào)用立即返回。第35頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信在可以使用套接字與遠(yuǎn)程設(shè)備通信之前,必須使用協(xié)議和網(wǎng)絡(luò)地址信息初始化套接字。Socket類的構(gòu)造函數(shù)具有指定套接字用來(lái)建立連接的地址族、套接字類型和協(xié)議類型的參數(shù)等功能。在基于TCP/IP的網(wǎng)絡(luò)上通信的關(guān)鍵代碼如下:Socket socket = new Socket(AddressF
36、amily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);使用UDP而不是TCP進(jìn)行通信的關(guān)鍵代碼如下:Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);參數(shù)說(shuō)明如下:(1)AddressFamily:AddressFamily枚舉,用來(lái)指定Socket類解析網(wǎng)絡(luò)地址的標(biāo)準(zhǔn)地址族。(2)SocketType:SocketType枚舉,用來(lái)指定套接字的類型。(3)ProtocolType:ProtocolTyp
37、e枚舉,用來(lái)指定在Socket上通信時(shí)使用的網(wǎng)絡(luò)協(xié)議。創(chuàng)建Socket類后,既可以開(kāi)始與遠(yuǎn)程終結(jié)點(diǎn)的連接,也可以接收來(lái)自遠(yuǎn)程設(shè)備的連接。第36頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信4. Socket類的屬性和方法Visual C#通過(guò)創(chuàng)建Socket類的實(shí)例來(lái)實(shí)現(xiàn)Socket的托管版本。在Visual C# 中創(chuàng)建完Socket實(shí)例后,可以通過(guò)此Socket實(shí)例的Bind方法綁定到網(wǎng)絡(luò)中指定的終結(jié)點(diǎn),也可以通過(guò)其Connect方法向指定的終結(jié)點(diǎn)建立連接。連接創(chuàng)建完畢后,就可以使用其Send或SendTo方法將數(shù)據(jù)發(fā)送到Socket;同樣使用其Receive或ReceiveFrom方法從Socket中讀
38、取數(shù)據(jù)。在Socket使用完畢后,請(qǐng)使用其Shutdown方法禁用Socket,并使用Close方法關(guān)閉Socket。表8.2和表8.3分別是Socket類中的常用屬性和方法及其簡(jiǎn)要說(shuō)明。第37頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信【例EX8_2】 設(shè)計(jì)WinForm應(yīng)用程序,將小寫字母轉(zhuǎn)換為大寫字母,其中包括客戶端和服務(wù)端,利用Socket將要轉(zhuǎn)換的小寫字母發(fā)送給服務(wù)端,服務(wù)端將接受到的小寫字母轉(zhuǎn)換為大寫字母并返回給客戶端。設(shè)計(jì)步驟:(1)新建客戶端WinForm項(xiàng)目新建WinForm項(xiàng)目并命名為“EX8_2_client”。(2)添加控件并設(shè)置屬性在Form1的設(shè)計(jì)視圖中,將此窗體調(diào)整到適當(dāng)?shù)拇笮?/p>
39、并將 “Text”屬性設(shè)為“客戶端”。從工具箱中拖放1個(gè)Button、2個(gè)Label和2個(gè)TextBox控件到窗體中,按如圖8.9所示方式布局控件。label1、label2和button1的Text屬性值分別設(shè)置為“發(fā)送的字符串:”、“接受并轉(zhuǎn)換為大寫的字符串:”和“轉(zhuǎn)換”。第38頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信(3)添加命名空間所要添加的命名空間為:using System.Net;using System.Net.Sockets;(4)添加事件及代碼雙擊“轉(zhuǎn)換”按鈕,其事件代碼如下所示。(5)新建服務(wù)端WinForm項(xiàng)目新建WinForm項(xiàng)目并命名為“EX8_2_server”。(6)添加
40、控件并設(shè)置屬性在Form1的設(shè)計(jì)視圖中將此窗體調(diào)整到適當(dāng)?shù)拇笮〔?“Text”屬性設(shè)為“服務(wù)端”。從工具箱中拖放1個(gè)Button、1個(gè)Label和1個(gè)TextBox控件到窗體中,按如圖8.10所示方式布局控件。label1和button1的Text屬性值分別設(shè)置為“從客戶端接受的字符串:”、“開(kāi)始監(jiān)聽(tīng)”。第39頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信(7)添加命名空間所要添加的命名空間為:using System.Net;using System.Net.Sockets;(8)添加事件及代碼雙擊“開(kāi)始監(jiān)聽(tīng)”按鈕,其事件代碼如下所示。第40頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信(9)運(yùn)行程序運(yùn)行此兩個(gè)程序,單擊
41、服務(wù)端的“開(kāi)始監(jiān)聽(tīng)”按鈕,在客戶端中輸入一些小寫字符串并單擊的“轉(zhuǎn)換”按鈕,運(yùn)行的結(jié)果如圖8.9和圖8.10所示。 圖8.9 客戶端 圖8.10 服務(wù)端第41頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信5. TcpClient類TcpClient類為TCP網(wǎng)絡(luò)服務(wù)提供客戶端連接。TcpClient類提供了一些簡(jiǎn)單的方法,用于在同步阻塞模式下通過(guò)網(wǎng)絡(luò)來(lái)連接、發(fā)送和接收流數(shù)據(jù)。為使TcpClient連接并交換數(shù)據(jù),使用TCP協(xié)議創(chuàng)建的TcpListener或Socket必須偵聽(tīng)是否有傳入的連接請(qǐng)求??梢允褂孟旅鎯煞N方法之一連接到該偵聽(tīng)器:(1)創(chuàng)建一個(gè)TcpClient,并調(diào)用三個(gè)可用的Connect方法之一:
42、TcpClient tcpClient=new TcpClient();/創(chuàng)建一個(gè)TcpClient/*使用下面三種方法之一連接到監(jiān)聽(tīng)器*/tcpClient.Connect (IPAddress, Int32) /使用指定的IP地址和端口號(hào)將客戶端連接到 TCP 主機(jī)tcpClient.Connect (IPAddress, Int32) /使用指定的IP地址和端口號(hào)將客戶端連接到遠(yuǎn)程TCP主機(jī)tcpClient.Connect (String, Int32) /將客戶端連接到指定主機(jī)上的指定端口第42頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信(2)使用遠(yuǎn)程主機(jī)的主機(jī)名和端口號(hào)創(chuàng)建TcpClient。此
43、構(gòu)造函數(shù)將自動(dòng)嘗試一個(gè)連接。TcpClient client = new TcpClient(hostname, port);要發(fā)送和接收數(shù)據(jù),可以使用GetStream方法來(lái)獲取一個(gè)NetworkStream。調(diào)用NetworkStream的Write和Read方法與遠(yuǎn)程主機(jī)之間發(fā)送和接收數(shù)據(jù)。使用Close方法釋放與TcpClient關(guān)聯(lián)的所有資源。TcpClient的常用屬性如表8.4所示,常用方法如表8.5所示。第43頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信6. TcpListener類TcpListener類從TCP網(wǎng)絡(luò)客戶端監(jiān)聽(tīng)連接。TcpListener類提供一些簡(jiǎn)單方法,用于在阻塞同步模
44、式下監(jiān)聽(tīng)和接受傳入連接請(qǐng)求??墒褂肐PEndPoint、本地IP地址及端口號(hào)或者僅使用端口號(hào),來(lái)創(chuàng)建TcpListener,創(chuàng)建監(jiān)聽(tīng)器兩種方法如下:(1)使用指定的本地終結(jié)點(diǎn)初始化TcpListener類的新實(shí)例。 TcpListener tcpListener=new TcpListener (IPEndPoint) (2)使用指定的本地IP地址和端口號(hào),監(jiān)聽(tīng)是否有傳入的連接嘗試。TcpListener tcpListener=new TcpListener (IPAddress, Int32) 可使用TcpClient或Socket來(lái)連接TcpListener??梢詫⒈镜豂P地址指定為An
45、y,將本地端口號(hào)指定為0(如果希望基礎(chǔ)服務(wù)提供程序?yàn)槌绦騿T分配這些值)。如果選擇這樣做,可在連接套接字后使用 LocalEndpoint 屬性來(lái)標(biāo)識(shí)已指定的信息。第44頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信Start方法用來(lái)開(kāi)始監(jiān)聽(tīng)傳入的連接請(qǐng)求。Start 將對(duì)傳入連接進(jìn)行排隊(duì),直至調(diào)用Stop方法或它已經(jīng)完成MaxConnections排隊(duì)為止??墒褂?AcceptSocket或AcceptTcpClient從傳入連接請(qǐng)求隊(duì)列提取連接。這兩種方法將阻止。如果要避免阻止,可首先使用Pending方法來(lái)確定隊(duì)列中是否有可用的連接請(qǐng)求。TcpListener類的常用屬性和方法的如表8.6和表8.7所示。
46、第45頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信7. NetworkStream類NetworkStream類提供用于網(wǎng)絡(luò)訪問(wèn)的基礎(chǔ)數(shù)據(jù)流。NetworkStream類提供在阻塞模式下通過(guò)Stream套接字發(fā)送和接收數(shù)據(jù)的方法??梢栽谕胶彤惒綌?shù)據(jù)傳輸時(shí)使用NetworkStream類。若要?jiǎng)?chuàng)建NetworkStream,必須提供連接的Socket。也可指定NetworkStream對(duì)所提供的Socket具有哪些FileAccess權(quán)限。以下是創(chuàng)建NetworkStream的幾種方法。(1)為指定的Socket創(chuàng)建NetworkStream類的新實(shí)例。NetworkStream networkStream
47、=new NetworkStream (Socket)(2)用指定的Socket 所屬權(quán)為指定的Socket初始化NetworkStream類的新實(shí)例。 NetworkStream networkStream=new NetworkStream (Socket, Boolean) (3)用指定的訪問(wèn)權(quán)限為指定的Socket 創(chuàng)建NetworkStream類的新實(shí)例。NetworkStream networkStream=new NetworkStream (Socket, FileAccess) (4)用指定的訪問(wèn)權(quán)限和指定的Socket所屬權(quán)為指定的Socket創(chuàng)建NetworkStream
48、類的新實(shí)例。NetworkStream networkStream=new NetworkStream (Socket, FileAccess, Boolean) 第46頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信將Write和Read方法用于簡(jiǎn)單的單線程同步阻塞I/O。若要使用不同的線程來(lái)處理I/O,則使用BeginWrite和EndWrite方法,或BeginRead和 EndRead方法進(jìn)行通信。NetworkStream不支持對(duì)網(wǎng)絡(luò)數(shù)據(jù)流的隨機(jī)訪問(wèn)。CanSeek屬性用于指示流是否支持查找,它的值始終為false;讀取Position屬性、讀取Length屬性或者調(diào)用 Seek方法都會(huì)引發(fā)NotSu
49、pportedException異常。NetworkStream類的常用屬性和方法如表8.8和表8.9所示。第47頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信【例EX8_3】 設(shè)計(jì)WinForm應(yīng)用程序發(fā)送并接受文件,其中包括發(fā)送文件和接受文件兩端。設(shè)計(jì)步驟:(1)新建發(fā)送文件端WinForm項(xiàng)目新建WinForm項(xiàng)目并命名為“EX8_3_sendfile”。(2)添加控件并設(shè)置屬性在Form1的設(shè)計(jì)視圖中將此窗體調(diào)整到適當(dāng)?shù)拇笮〔?“Text”屬性設(shè)為“發(fā)送文件”。從工具箱中拖放1個(gè)Button控件到窗體中,按如圖8.11所示方式布局控件。button1的Text屬性設(shè)置為“選擇文件并發(fā)送”。(3)添加
50、命名空間所要添加的命名空間為:using System.Net;using System.Net.Sockets;using System.IO;第48頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信(4)添加事件及代碼雙擊“選擇文件并發(fā)送”按鈕,其事件代碼如下所示。(5)新建接受文件端WinForm項(xiàng)目新建WinForm項(xiàng)目并命名為“EX8_3_receivefile”。(6)設(shè)置屬性此窗體在運(yùn)行時(shí)是不可見(jiàn)的,F(xiàn)orm1的Text屬性設(shè)置為“接受文件”。(7)添加命名空間所要添加的命名空間為:using System.Net;using System.Net.Sockets;using System.IO;(
51、8)添加事件及代碼雙擊Form1窗體,其事件代碼如下所示。第49頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信(9)運(yùn)行程序運(yùn)行此兩個(gè)程序,單擊發(fā)送文件端的“選擇文件并發(fā)送”按鈕,彈出打開(kāi)文件對(duì)話框,選擇要發(fā)送的文件,此時(shí)接受文件端彈出保存文件對(duì)話框,輸入要保存文件的文件名和后綴名,單擊“保存”按鈕,則文件接受成功。發(fā)送文件端運(yùn)行的結(jié)果如圖8.11所示。按【Ctrl+Alt+Del】組合鍵打開(kāi)Windows任務(wù)管理器,關(guān)閉接受端進(jìn)程,如圖8.12所示。 圖8.11 發(fā)送文件端 圖8.12 Windows任務(wù)管理器第50頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信8. UdpClient類UdpClient類是提供用戶數(shù)據(jù)報(bào)
52、(UDP)網(wǎng)絡(luò)服務(wù)。UdpClient類提供了一些簡(jiǎn)單的方法,用于在阻塞同步模式下發(fā)送和接收無(wú)連接UDP數(shù)據(jù)報(bào)。因?yàn)閁DP是無(wú)連接傳輸協(xié)議,所以不需要在發(fā)送和接收數(shù)據(jù)前建立遠(yuǎn)程主機(jī)連接。但可以選擇使用下面兩種方法之一來(lái)建立默認(rèn)遠(yuǎn)程主機(jī):(1)使用遠(yuǎn)程主機(jī)名和端口號(hào)作為參數(shù)創(chuàng)建UdpClient類的實(shí)例。UdpClient udpClient=new UdpClient(hostname,port)(2)創(chuàng)建UdpClient類的實(shí)例,然后調(diào)用Connect方法。UdpClient udpClient=new UdpClient();/*使用下面三種方法之一建立默認(rèn)遠(yuǎn)程主機(jī)*/udpClient
53、.Connect (IPEndPoint) /使用指定的網(wǎng)絡(luò)終結(jié)點(diǎn)建立默認(rèn)遠(yuǎn)程主機(jī)udpClient.Connect (IPAddress, Int32) /使用指定的IP地址和端口號(hào)建立默認(rèn)遠(yuǎn)程主機(jī)udpClient.Connect (String, Int32) /使用指定的主機(jī)名和端口號(hào)建立默認(rèn)遠(yuǎn)程主機(jī)第51頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信可以使用在UdpClient中提供的任何一種發(fā)送方法將數(shù)據(jù)發(fā)送到遠(yuǎn)程設(shè)備。使用 Receive方法可以從遠(yuǎn)程主機(jī)接收數(shù)據(jù)。UdpClient類的常用屬性和方法如表8.10和表8.11所示?!纠鼸X8_4】 設(shè)計(jì)WinForm應(yīng)用程序發(fā)送廣播信息并接受廣播
54、信息,其中包括服務(wù)端和接受客戶端,服務(wù)端用于發(fā)送廣播信息,而客戶端用于接收廣播信息。 設(shè)計(jì)步驟:(1)新建服務(wù)端WinForm項(xiàng)目新建WinForm項(xiàng)目并命名為“EX8_4_server”。(2)添加控件并設(shè)置屬性在Form1的設(shè)計(jì)視圖中,將此窗體調(diào)整到適當(dāng)?shù)拇笮〔?“Text”屬性設(shè)為“服務(wù)端”。從工具箱中拖放1個(gè)Button、1個(gè)Label和1個(gè)Open File Dialog組件到窗體中,按如圖8.11所示進(jìn)行布局控件。button1的Text屬性設(shè)置為“選擇文件并發(fā)送”。第52頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信(3)添加命名空間所要添加的命名空間為:using System.Net;us
55、ing System.Net.Sockets;(4)添加事件及代碼雙擊“開(kāi)始廣播”按鈕,其事件代碼如下所示:private void button1_Click(object sender, EventArgs e) UdpClient udpClient = new UdpClient(); try udpClient.Connect(IPAddress.Parse(55), 5000); Byte sendBytes = Encoding.ASCII.GetBytes(textBox1.Text.Trim(); udpClient.Send(sendBytes, sendBytes.Len
56、gth); /發(fā)送信息 udpClient.Close(); catch (Exception ex) Console.WriteLine(ex.Message.ToString(); 第53頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信(5)新建客戶端WinForm項(xiàng)目新建WinForm項(xiàng)目并命名為“EX8_4_client”。(6)設(shè)置屬性此窗體在運(yùn)行時(shí)是不可見(jiàn)的,從工具箱中拖放1個(gè)Save File Dialog組件到窗體中,F(xiàn)orml的Text屬性設(shè)置為“接受文件”。(7)添加命名空間所要添加的命名空間為:using System.Net;using System.Net.Sockets;第54頁(yè),共
57、76頁(yè)。L1. 網(wǎng)絡(luò)通信(8)添加事件及代碼雙擊Form1窗體,其事件代碼如下所示:private void Form1_Load (object sender, EventArgs e)UdpClient udpClient = new UdpClient(5000); try IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0); Byte receiveBytes = udpClient.Receive(ref RemoteIpEndPoint); /接受消息 string returnData = Encoding
58、.ASCII.GetString(receiveBytes); textBox1.Text = 消息來(lái)源IP: + RemoteIpEndPoint.Address.ToString() +端口號(hào):+ RemoteIpEndPoint.Port.ToString()+rn內(nèi)容:+returnData.ToString(); udpClient.Close(); /釋放對(duì)象 catch (Exception ex) Console.WriteLine(ex.Message); 第55頁(yè),共76頁(yè)。L1. 網(wǎng)絡(luò)通信(9)運(yùn)行程序運(yùn)行此兩個(gè)程序,單擊客戶端的“開(kāi)始監(jiān)聽(tīng)”按鈕,開(kāi)始監(jiān)聽(tīng)廣播信息。在服務(wù)
59、端中輸入“今天下午3點(diǎn)鐘有會(huì)!”并單擊“開(kāi)始廣播”按鈕,如圖8.13所示??蛻舳私邮芟⒉@示,如圖8.14所示。 圖8.13 服務(wù)端圖8.14 客戶端返回第56頁(yè),共76頁(yè)。L8.3 主界面的設(shè)計(jì)L1. 線程1. 線程簡(jiǎn)介多線程程序中,在一個(gè)線程必須等待的時(shí)候,CPU可以運(yùn)行其他線程而不是等待,這就大大提高了程序的效率。然而,我們也必須認(rèn)識(shí)到線程本身可能存在影響系統(tǒng)性能的不利方面,才能正確使用線程。不利方面主要有:(1)線程也是程序,所以線程需要占用內(nèi)存,線程越多占用內(nèi)存也越多。(2)多線程需要協(xié)調(diào)和管理,所以需要占用CPU時(shí)間來(lái)跟蹤線程。(3)線程之間對(duì)共享資源的訪問(wèn)會(huì)相互影響,必須解決爭(zhēng)
60、用共享資源的問(wèn)題。 (4)線程太多會(huì)導(dǎo)致控制太復(fù)雜,最終可能造成很多Bug。第57頁(yè),共76頁(yè)。L1. 線程當(dāng)啟動(dòng)一個(gè)可執(zhí)行程序時(shí),將創(chuàng)建一個(gè)主線程,默認(rèn)情況下,C#程序具有一個(gè)線程。此線程執(zhí)行程序中以Main方法開(kāi)始和結(jié)束的代碼。Main直接或間接執(zhí)行的每一個(gè)命令都由默認(rèn)線程(或主線程)執(zhí)行,當(dāng)Main返回時(shí)此線程也將終止。例如打開(kāi)【EX8_3_server】的“Program.cs”文件,其代碼如下:static class Program / / 應(yīng)用程序的主入口點(diǎn)。 / STAThread static void Main() Application.EnableVisualStyle
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年房地產(chǎn)開(kāi)發(fā)土方合同
- 2024年文化藝術(shù)節(jié)活動(dòng)組織與承辦合同
- 2024年修訂版技術(shù)轉(zhuǎn)讓合同
- 2024年文化旅游綜合體開(kāi)發(fā)合作協(xié)議
- DB4117T 233-2018 夏芝麻高產(chǎn)高效栽培技術(shù)規(guī)程
- DB4117T 169.13-2023 動(dòng)物疫病流行病學(xué)調(diào)查技術(shù)規(guī)范 第13部分:雞傳染性支氣管炎
- 2024年工業(yè)用水管道安裝協(xié)議
- 2024年度××建筑工程項(xiàng)目施工合同
- 質(zhì)檢個(gè)人年度總結(jié)(7篇)
- 2024年技術(shù)轉(zhuǎn)讓合同:研發(fā)機(jī)構(gòu)將自主研發(fā)的技術(shù)轉(zhuǎn)讓給企業(yè)
- (高清版)JT∕T 1402-2022 交通運(yùn)輸行政執(zhí)法基礎(chǔ)裝備配備及技術(shù)要求
- 中華聯(lián)合保險(xiǎn)集團(tuán)股份有限公司行測(cè)筆試題庫(kù)2024
- 印刷服務(wù) 投標(biāo)方案(技術(shù)方案)
- 必修一《數(shù)據(jù)與計(jì)算》復(fù)習(xí)提綱與練習(xí)題
- 三級(jí)公立醫(yī)院績(jī)效考核微創(chuàng)手術(shù)目錄(2022版)
- 危險(xiǎn)駕駛罪課件講解
- HJ 704-2014 土壤 有效磷的測(cè)定 碳酸氫鈉浸提-鉬銻抗分光光度法
- 四年級(jí)寒假奧數(shù)培優(yōu)講義-4-04-倒推法解題4-講義-教師
- 教師心理健康B證心得體會(huì)7篇
- DZ∕T 0317-2018 陸上石油天然氣開(kāi)采業(yè)綠色礦山建設(shè)規(guī)范(正式版)
- 同底數(shù)冪的乘法練習(xí)
評(píng)論
0/150
提交評(píng)論