久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

C# .net2.0 套接字編程實(shí)例 UDP TCP通信

 ShangShujie 2008-01-24
C# .net2.0 套接字編程實(shí)例 UDP TCP通信

         首先從原理上解釋一下采用Socket接口的網(wǎng)絡(luò)通訊,這里以最常用的C/S模式作為范例,,首先,,服務(wù)端有一個(gè)進(jìn)程(或多個(gè)進(jìn)程)在指定的端口等待客戶來 連接,服務(wù)程序等待客戶的連接信息,,一旦連接上之后,就可以按設(shè)計(jì)的數(shù)據(jù)交換方法和格式進(jìn)行數(shù)據(jù)傳輸,??蛻舳嗽谛枰臅r(shí)刻發(fā)出向服務(wù)端的連接請(qǐng)求。這里為 了便于理解,,提到了一些調(diào)用及其大致的功能,。使用socket調(diào)用后,,僅產(chǎn)生了一個(gè)可以使用的socket描述符,這時(shí)還不能進(jìn)行通信,,還要使用其他的調(diào) 用,,以使得socket所指的結(jié)構(gòu)中使用的信息被填寫完。

  在使用TCP協(xié)議時(shí),,一般服務(wù)端進(jìn)程先使用socket調(diào)用得到一個(gè)描述符,,然后使用bind調(diào)用將一個(gè)名字 與socket描述符連接起來,對(duì)于Internet域就是將Internet地址聯(lián)編到socket,。之后,,服務(wù)端使用listen調(diào)用指出等待服務(wù)請(qǐng) 求隊(duì)列的長(zhǎng)度。然后就可以使用accept調(diào)用等待客戶端發(fā)起連接,,一般是阻塞等待連接,,一旦有客戶端發(fā)出連接,accept返回客戶的地址信息,,并返回 一個(gè)新的socket描述符,,該描述符與原先的socket有相同的特性,這時(shí)服務(wù)端就可以使用這個(gè)新的socket進(jìn)行讀寫操作了,。一般服務(wù)端可能在 accept返回后創(chuàng)建一個(gè)新的進(jìn)程進(jìn)行與客戶的通信,,父進(jìn)程則再到accept調(diào)用處等待另一個(gè)連接??蛻舳诉M(jìn)程一般先使用socket調(diào)用得到一個(gè) socket描述符,,然后使用connect向指定的服務(wù)器上的指定端口發(fā)起連接,一旦連接成功返回,,就說明已經(jīng)建立了與服務(wù)器的連接,,這時(shí)就可以通過 socket描述符進(jìn)行讀寫操作了。

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

  ·Socket類這個(gè)低層的類用于管理連接,,WebRequest,TcpClient和UdpClient在內(nèi)部使用這個(gè)類,。

  ·NetworkStream類這個(gè)類是從Stream派生出來的,,它表示來自網(wǎng)絡(luò)的數(shù)據(jù)流

  ·TcpClient類允許創(chuàng)建和使用TCP連接

  ·TcpListener類允許監(jiān)聽傳入的TCP連接請(qǐng)求

  ·UdpClient類用于UDP客戶創(chuàng)建連接(UDP是另外一種TCP協(xié)議,但沒有得到廣泛的使用,,主要用于本地網(wǎng)絡(luò))

  下面我們來看一個(gè)基于Socket的雙機(jī)通信代碼的C#版本

  首先創(chuàng)建Socket對(duì)象的實(shí)例,,這可以通過Socket類的構(gòu)造方法來實(shí)現(xiàn):

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

  其中,addressFamily 參數(shù)指定 Socket 使用的尋址方案,,socketType 參數(shù)指定 Socket 的類型,,protocolType 參數(shù)指定 Socket 使用的協(xié)議。

  下面的示例語句創(chuàng)建一個(gè) Socket,,它可用于在基于 TCP/IP 的網(wǎng)絡(luò)(如 Internet)上通訊,。

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

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

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

  一旦創(chuàng)建 Socket,,在客戶端,,你將可以通過Connect方法連接到指定的服務(wù)器(你可以在Connect方法前Bind端口,就是以指定的端口發(fā)起連接,,如 果不事先Bind端口號(hào)的話,,系統(tǒng)會(huì)默認(rèn)在1024到5000隨機(jī)綁定一個(gè)端口號(hào)),并通過Send方法向遠(yuǎn)程服務(wù)器發(fā)送數(shù)據(jù),,而后可以通過 Receive從服務(wù)端接收數(shù)據(jù),;而在服務(wù)器端,你需要使用Bind方法綁定所指定的接口使Socket與一個(gè)本地終結(jié)點(diǎn)相聯(lián),,并通過Listen方法偵 聽該接口上的請(qǐng)求,,當(dāng)偵聽到用戶端的連接時(shí),調(diào)用Accept完成連接的操作,,創(chuàng)建新的Socket以處理傳入的連接請(qǐng)求,。使用完 Socket 后,使用 Close 方法關(guān)閉 Socket,。

  可以看出,,以上許多方法包含EndPoint類型的參數(shù),在Internet中,,TCP/IP 使用一個(gè)網(wǎng)絡(luò)地址和一個(gè)服務(wù)端口號(hào)來唯一標(biāo)識(shí)設(shè)備,。網(wǎng)絡(luò)地址標(biāo)識(shí)網(wǎng)絡(luò)上的特定設(shè)備;端口號(hào)標(biāo)識(shí)要連接到的該設(shè)備上的特定服務(wù),。網(wǎng)絡(luò)地址和服務(wù)端口的組合稱 為終結(jié)點(diǎn),,在 .NET 框架中正是由 EndPoint 類表示這個(gè)終結(jié)點(diǎn),它提供表示網(wǎng)絡(luò)資源或服務(wù)的抽象,,用以標(biāo)志網(wǎng)絡(luò)地址等信息,。.Net同時(shí)也為每個(gè)受支持的地址族定義了 EndPoint 的子代;對(duì)于 IP 地址族,,該類為 IPEndPoint,。IPEndPoint 類包含應(yīng)用程序連接到主機(jī)上的服務(wù)所需的主機(jī)和端口信息,通過組合服務(wù)的主機(jī)IP地址和端口號(hào),,IPEndPoint 類形成到服務(wù)的連接點(diǎn),。

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

  ·IPAddress類:IPAddress 類包含計(jì)算機(jī)在 IP 網(wǎng)絡(luò)上的地址,。其Parse方法可將 IP 地址字符串轉(zhuǎn)換為 IPAddress 實(shí)例,。下面的語句創(chuàng)建一個(gè) IPAddress 實(shí)例:

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

  需要知道的是:Socket 類支持兩種基本模式:同步和異步。其區(qū)別在于:在同步模式中,,按塊傳輸,,對(duì)執(zhí)行網(wǎng)絡(luò)操作的函數(shù)(如 Send 和 Receive)的調(diào)用一直等到所有內(nèi)容傳送操作完成后才將控制返回給調(diào)用程序。在異步模式中,,是按位傳輸,,需要指定發(fā)送的開始和結(jié)束。同步模式是最常用 的模式,,我們這里的例子也是使用同步模式,。

  下面看一個(gè)完整的例子,client向server發(fā)送一段測(cè)試字符串,,server接收并顯示出來,,給予client成功響應(yīng)。

//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和端口轉(zhuǎn)化為IPEndPoint實(shí)例
Socket c = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//創(chuàng)建一個(gè)Socket
Console.WriteLine("Conneting...");
c.Connect(ipe);//連接到服務(wù)器
string sendStr = "hello!This is a socket test";
byte[] bs = Encoding.ASCII.GetBytes(sendStr);
Console.WriteLine("Send Message");
c.Send(bs, bs.Length, 0);//發(fā)送測(cè)試信息
string recvStr = "";
byte[] recvBytes = new byte[1024];
int bytes;
bytes = c.Receive(recvBytes, recvBytes.Length, 0);//從服務(wù)器端接受返回信息
recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);
Console.WriteLine("Client Get Message:{0}", recvStr);//顯示服務(wù)器返回信息
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);//創(chuàng)建一個(gè)Socket類
s.Bind(ipe);//綁定2000端口
s.Listen(0);//開始監(jiān)聽
Console.WriteLine("Wait for connect");
Socket temp = s.Accept();//為新建連接創(chuàng)建新的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命名空間還提供了兩個(gè)抽象高級(jí)類TCPClient和UDPClient和用于通訊流處理的NetWorkStream,讓我們看下例子

  客戶端

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

  服務(wù)端

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

  服務(wù)端用TcpListener監(jiān)聽,然后把連接的對(duì)象實(shí)例化為一個(gè)TcpClient,調(diào)用TcpClient.GetStream()方法,返回網(wǎng)絡(luò)流實(shí)例化為一個(gè)NetworlStream流,下面就是用流的方法進(jìn)行Send,Receive

  如果是UdpClient的話,就直接UdpClient實(shí)例化,然后調(diào)用UdpClient的Send和 Receive方法,需要注意的事,UdpClient沒有返回網(wǎng)絡(luò)流的方法,就是說沒有GetStream方法,所以無法流化,而且使用Udp通信的時(shí) 候,不要服務(wù)器監(jiān)聽。

  現(xiàn)在我們大致了解了.Net Socket通信的流程,,下面我們來作一個(gè)稍微復(fù)雜點(diǎn)的程序,,一個(gè)廣播式的C/S聊天程序。

客戶端設(shè)計(jì)需要一個(gè)1個(gè)ListBox,,用于顯示聊天內(nèi)容,,一個(gè)TextBox輸入你要說的話,一個(gè)Button發(fā)送留言,,一個(gè)Button建立連接,。

  點(diǎn)擊建立連接的Button后出來一個(gè)對(duì)話框,提示輸入連接服務(wù)器的IP,,端口,,和你的昵稱,啟動(dòng)一個(gè)接受線程,,負(fù)責(zé)接受從服務(wù)器傳來的信息并顯示在ListBox上面,。

  服務(wù)器端2個(gè)Button,一個(gè)啟動(dòng)服務(wù),,一個(gè)T掉已建立連接的客戶端,,一個(gè)ListBox顯示連接上的客戶端的Ip和端口。

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

  還有一個(gè)就是接收線程,,我這里簡(jiǎn)單寫成一個(gè)While(ture)循環(huán),不斷判斷是否有信息流入,,有就接收,,并顯示在ListBox上,,這里有問題,在.Net2.0里面,,交錯(cuò)線程修改窗體空間屬性的時(shí)候會(huì)引發(fā)一個(gè)異常,,不可以直接修改,需要定義一個(gè)委托來修改,。

  當(dāng)客戶端需要斷開連接的時(shí)候,,比如點(diǎn)擊窗體右上角的XX,就需要定義一個(gè)this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Closing);(.Net2.0是 FormClosing系統(tǒng)事件),,在Closing()函數(shù)里面,,發(fā)送Close字符給服務(wù)端,服務(wù)器判斷循環(huán)判斷所有的連接上的客戶端傳來的信息,,如 果是以Close開頭,,斷開與其的連接??吹竭@里,,讀者就會(huì)問了,如果我在聊天窗口輸入Close是不是也斷開連接呢,?不是的,,在聊天窗口輸入的信息傳給 服務(wù)器的時(shí)候開頭都要加上Ip信息和昵稱,所以不會(huì)沖突,。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多