国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發(fā) > 綜合 > 正文

C#網(wǎng)絡(luò)編程概述

2024-07-21 02:19:01
字體:
供稿:網(wǎng)友

c#網(wǎng)絡(luò)編程概述

微軟下一代互聯(lián)網(wǎng)開發(fā)工具vs.net已于三月份在全國范圍推出,其中的一門新興語言c#正被越來越多的開發(fā)者所接受并運(yùn)用。
  c#作為一門集眾家之長的語言,在各個(gè)方面尤其是網(wǎng)絡(luò)編程方面有著很大的優(yōu)勢。本文就向大家介紹一下用c#進(jìn)行網(wǎng)絡(luò)編程的一些基本知識和方法。
  微軟的.net框架為我們進(jìn)行網(wǎng)絡(luò)編程提供了以下兩個(gè)名字空間:system.net以及system.net.sockets。通過合理運(yùn)用其中的類和方法,我們可以很容易地編寫出各種網(wǎng)絡(luò)應(yīng)用程序。這種網(wǎng)絡(luò)應(yīng)用程序既可以是基于流套接字的,也可以是基于數(shù)據(jù)報(bào)套接字的。而基于流套接字的通訊中采用最廣泛的協(xié)議就是tcp協(xié)議,基于數(shù)據(jù)報(bào)套接字的通訊中采用最廣泛的自然就是udp協(xié)議了。

  下面我重點(diǎn)向大家介紹c#網(wǎng)絡(luò)編程中的一些類:dns類、iphostentry類、ipendpoint類以及socket類,最后我會給出相應(yīng)的實(shí)例以加深讀者的理解。
dns 類:

  向使用 tcp/ip internet 服務(wù)的應(yīng)用程序提供域名服務(wù)。其resolve()方法查詢dns服務(wù)器以將用戶友好的域名(如"www.google.com")映射到數(shù)字形式的 internet 地址(如 192.168.1.1)。resolve()方法返回一個(gè)iphostenty實(shí)例,該實(shí)例包含所請求名稱的地址和別名的列表。大多數(shù)情況下,可以使用 addresslist 數(shù)組中返回的第一個(gè)地址。

resolve()方法的函數(shù)原型如下:

public static iphostentry resolve(string hostname);

下面的代碼獲取一個(gè) ipaddress 實(shí)例,該實(shí)例包含服務(wù)器 www.google.com 的ip地址:

iphostentry iphostinfo = dns.resolve("www.google.com");

ipaddress ipaddress = iphostinfo.addresslist[0];

不過在dns類中,除了通過resolve()方法,你還可以通過gethostbyaddress()方法以及gethostbyname()方法來得到相應(yīng)的iphostentry實(shí)例,函數(shù)原型如下:

public static iphostentry gethostbyaddress(string ipaddress);

public static iphostentry gethostbyname(string hostname);

下面的代碼顯示了如何分別運(yùn)用以上兩種方法獲得包含服務(wù)器www.google.com的相關(guān)信息的iphostentry實(shí)例:

iphostentry hostinfo=dns.gethostbyaddress(“192.168.1.1”);

iphostentry hostinfo=dns.gethostbyname("www.google.com");

在使用以上方法時(shí),你將可能需要處理以下幾種異常:

socketexception異常:訪問socket時(shí)操作系統(tǒng)發(fā)生錯(cuò)誤引發(fā)

argumentnullexception異常:參數(shù)為空引用引發(fā)

objectdisposedexception異常:socket已經(jīng)關(guān)閉引發(fā)

以上,我向大家簡要地介紹了dns類中一些方法以及其用法,并列舉出了可能出現(xiàn)的異常,下面就讓我們轉(zhuǎn)到和dns類密切相關(guān)的iphostentry類。
iphostentry類:

該類的實(shí)例對象中包含了internet主機(jī)的地址相關(guān)信息。此類型的所有公共靜態(tài)成員對多線程操作而言都是安全的,但不保證任何實(shí)例成員是線程安全的。其中主要的一些屬性有:addresslist屬性、aliases屬性以及hostname屬性。

addresslist屬性和aliases屬性的作用分別是獲取或設(shè)置與主機(jī)關(guān)聯(lián)的ip地址列表以及獲取或設(shè)置與主機(jī)關(guān)聯(lián)的別名列表。其中addresslist屬性值是一個(gè)ipaddress類型的數(shù)組,包含解析為aliases屬性中包含的主機(jī)名的ip地址;aliases屬性值是一組字符串,包含解析為addresslist 屬性中的ip地址的dns名。而hostname屬性比較好理解,它包含了服務(wù)器的主要主機(jī)名,這光從名稱上就可以知道了。如果服務(wù)器的dns項(xiàng)定義了附加別名,則可在aliases屬性中使用這些別名。

下面的代碼列出了服務(wù)器www.google.com的相關(guān)別名列表以及ip地址列表的長度并將所有的ip地址列出:

iphostentry iphost = dns.resolve("www.google.com/");

string[] aliases = iphost.aliases;

console.writeline(aliases.length);


ipaddress[] addr = iphost.addresslist;

console.writeline(addr.length);

for(int i= 0; i < addr.length ; i++)

{

console.writeline(addr[i]);

}

介紹完iphostentry類,我們能獲得了所要連接的主機(jī)的相關(guān)ip地址以及別名列表,但是真正要和主機(jī)取得連接還需要一個(gè)很重要的類-ipendpoint類。

ipendpoint類:

在internet中,tcp/ip使用一個(gè)網(wǎng)絡(luò)地址和一個(gè)服務(wù)端口號來唯一標(biāo)識設(shè)備。網(wǎng)絡(luò)地址標(biāo)識網(wǎng)絡(luò)上的特定設(shè)備;端口號標(biāo)識要連接到的該設(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的子代;對于ip地址族,該類為ipendpoint。ipendpoint類包含應(yīng)用程序連接到主機(jī)上的服務(wù)所需的主機(jī)和端口信息,通過組合服務(wù)的主機(jī)ip地址和端口號,ipendpoint類形成到服務(wù)的連接點(diǎn)。

在ipendpoint類中有兩個(gè)很有用的構(gòu)造函數(shù):

public ipendpoint(long, int);

public ipendpoint(ipaddress, int);

它們的作用就是用指定的地址和端口號初始化 ipendpoint 類的新實(shí)例。該類中的屬性有:address屬性、addressfamily屬性以及port屬性,這些屬性相對比較容易理解,這里就不作多介紹。下面的代碼顯示了如何取得服務(wù)器www.google.com的終結(jié)點(diǎn):

iphostentry iphost = dns.resolve("www.google.com");

ipaddress[] addr = iphost.addresslist;

ipendpoint ep = new ipendpoint(addr[0],80);

這樣,我們已經(jīng)了解了和主機(jī)取得連接的一些必要的基本類,有了這些知識,我們就可以運(yùn)用下面的socket類真正地和主機(jī)取得連接并進(jìn)行通訊了。

socket類:

socket類是包含在system.net.sockets名字空間中的一個(gè)非常重要的類。一個(gè)socket實(shí)例包含了一個(gè)本地以及一個(gè)遠(yuǎn)程的終結(jié)點(diǎn),就像上面介紹的那樣,該終結(jié)點(diǎn)包含了該socket實(shí)例的一些相關(guān)信息。

需要知道的是socket 類支持兩種基本模式:同步和異步。其區(qū)別在于:在同步模式中,對執(zhí)行網(wǎng)絡(luò)操作的函數(shù)(如send和receive)的調(diào)用一直等到操作完成后才將控制返回給調(diào)用程序。在異步模式中,這些調(diào)用立即返回。

下面我們重點(diǎn)討論同步模式的socket編程。首先,同步模式的socket編程的基本過程如下:

1. 創(chuàng)建一個(gè)socket實(shí)例對象。

2. 將上述實(shí)例對象連接到一個(gè)具體的終結(jié)點(diǎn)(endpoint)。

3. 連接完畢,就可以和服務(wù)器進(jìn)行通訊:接收并發(fā)送信息。

4. 通訊完畢,用shutdown()方法來禁用socket。

5. 最后用close()方法來關(guān)閉socket。

知道了以上基本過程,我們就開始進(jìn)一步實(shí)現(xiàn)連接并通訊了。在使用之前,你需要首先創(chuàng)建socket對象的實(shí)例,這可以通過socket類的構(gòu)造方法來實(shí)現(xiàn):

public socket(addressfamily addressfamily,sockettype sockettype,protocoltype protocoltype);

其中,addressfamily 參數(shù)指定socket使用的尋址方案,比如addressfamily.internetwork表明為ip版本4的地址;sockettype參數(shù)指定socket的類型,比如sockettype.stream表明連接是基于流套接字的,而sockettype.dgram表示連接是基于數(shù)據(jù)報(bào)套接字的。protocoltype參數(shù)指定socket使用的協(xié)議,比如protocoltype.tcp表明連接協(xié)議是運(yùn)用tcp協(xié)議的,而protocol.udp則表明連接協(xié)議是運(yùn)用udp協(xié)議的。

在創(chuàng)建了socket實(shí)例后,我們就可以通過一個(gè)遠(yuǎn)程主機(jī)的終結(jié)點(diǎn)和它取得連接,運(yùn)用的方法就是connect()方法:

public connect (endpoint ep);

該方法只可以被運(yùn)用在客戶端。進(jìn)行連接后,我們可以運(yùn)用套接字的connected屬性來驗(yàn)證連接是否成功。如果返回的值為true,則表示連接成功,否則就是失敗。下面的代碼就顯示了如何創(chuàng)建socket實(shí)例并通過終結(jié)點(diǎn)與之取得連接的過程:

iphostentry iphost = dns.resolve("http://www.google.com/");

string []aliases = iphost.aliases;

ipaddress[] addr = iphost.addresslist;

endpoint ep = new ipendpoint(addr[0],80);

socket sock = new socket(addressfamily.internetwork,sockettype.stream,protocoltype.tcp);

sock.connect(ep);

if(sock.connected)

console.writeline("ok");
一旦連接成功,我們就可以運(yùn)用send()和receive()方法來進(jìn)行通訊。

send()方法的函數(shù)原型如下:

public int send (byte[] buffer, int size, socketflags flags);

其中,參數(shù)buffer包含了要發(fā)送的數(shù)據(jù),參數(shù)size表示要發(fā)送數(shù)據(jù)的大小,而參數(shù)flags則可以是以下一些值:socketflags.none、socketflags.dontroute、socketflags.outofbnd。

該方法返回的是一個(gè)system.int32類型的值,它表明了已發(fā)送數(shù)據(jù)的大小。同時(shí),該方法還有以下幾種已被重載了的函數(shù)實(shí)現(xiàn):

public int send (byte[] buffer);

public int send (byte[] buffer, socketflags flags);

public int send (byte[] buffer,int offset, int size, socketflags flags);

介紹完send()方法,下面是receive()方法,其函數(shù)原型如下:

public int receive(byte[] buffer, int size, socketflags flags);

其中的參數(shù)和send()方法的參數(shù)類似,在這里就不再贅述。

同樣,該方法還有以下一些已被重載了的函數(shù)實(shí)現(xiàn):

public int receive (byte[] buffer);

public int receive (byte[] buffer, socketflags flags);

public int receive (byte[] buffer,int offset, int size, socketflags flags);

在通訊完成后,我們就通過shutdown()方法來禁用socket,函數(shù)原型如下:

public void shutdown(socketshutdown how);

其中的參數(shù)how表明了禁用的類型,soketshutdown.send表明關(guān)閉用于發(fā)送的套接字;soketshutdown.receive表明關(guān)閉用于接收的套接字;而soketshutdown.both則表明發(fā)送和接收的套接字同時(shí)被關(guān)閉。

應(yīng)該注意的是在調(diào)用close()方法以前必須調(diào)用shutdown()方法以確保在socket關(guān)閉之前已發(fā)送或接收所有掛起的數(shù)據(jù)。一旦shutdown()調(diào)用完畢,就調(diào)用close()方法來關(guān)閉socket,其函數(shù)原型如下:

public void close();

該方法強(qiáng)制關(guān)閉一個(gè)socket連接并釋放所有托管資源和非托管資源。該方法在內(nèi)部其實(shí)是調(diào)用了方法dispose(),該函數(shù)是受保護(hù)類型的,其函數(shù)原型如下:

protected virtual void dispose(bool disposing);

其中,參數(shù)disposing為true或是false,如果為true,則同時(shí)釋放托管資源和非托管資源;如果為false,則僅釋放非托管資源。因?yàn)閏lose()方法調(diào)用dispose()方法時(shí)的參數(shù)是true,所以它釋放了所有托管資源和非托管資源。

這樣,一個(gè)socket從創(chuàng)建到連接到通訊最后的關(guān)閉的過程就完成了。雖然整個(gè)過程比較復(fù)雜,但相對以前在sdk或是其他環(huán)境下進(jìn)行socket編程,這個(gè)過程就顯得相當(dāng)輕松了。

最后,我就綜合以上c#網(wǎng)絡(luò)編程的一些知識,向大家展示一個(gè)很好的實(shí)例。該實(shí)例是一個(gè)運(yùn)用socket的基于同步模式的客戶端應(yīng)用程序,它首先通過解析服務(wù)器的ip地址建立一個(gè)終結(jié)點(diǎn),同時(shí)創(chuàng)建一個(gè)基于流套接字的socket連接,其運(yùn)用的協(xié)議是tcp協(xié)議。通過該socket就可以發(fā)送獲取網(wǎng)頁的命令,再通過該socket獲得服務(wù)器上默認(rèn)的網(wǎng)頁,最后通過文件流將獲得的數(shù)據(jù)寫入本機(jī)文件。這樣就完成了網(wǎng)頁的下載工作了,程序運(yùn)行的效果如下所示:


源代碼如下:(其中主要的函數(shù)為dosocketget())

using system;
using system.drawing;
using system.collections;
using system.componentmodel;
using system.windows.forms;
using system.data;
using system.net;
using system.net.sockets;
using system.text;
using system.io;

namespace socketsample
{

///
/// form1 的摘要說明。
///

public class form1 : system.windows.forms.form
{

private system.windows.forms.label label1;
private system.windows.forms.label label2;
private system.windows.forms.button download;
private system.windows.forms.textbox serveraddress;
private system.windows.forms.textbox filename;

///
/// 必需的設(shè)計(jì)器變量。
///

private system.componentmodel.container components = null;

public form1()
{
//
// windows 窗體設(shè)計(jì)器支持所必需的
//

initializecomponent();

//
// todo: 在 initializecomponent 調(diào)用后添加任何構(gòu)造函數(shù)代碼
//

}


///
/// 清理所有正在使用的資源。
///
protected override void dispose( bool disposing )
{

if( disposing )

{
if (components != null)
{

components.dispose();

}

}

base.dispose( disposing );

}


#region windows form designer generated code

///

/// 設(shè)計(jì)器支持所需的方法 - 不要使用代碼編輯器修改

/// 此方法的內(nèi)容。

///

private void initializecomponent()

{

this.label1 = new system.windows.forms.label();

this.label2 = new system.windows.forms.label();

this.download = new system.windows.forms.button();

this.serveraddress = new system.windows.forms.textbox();

this.filename = new system.windows.forms.textbox();

this.suspendlayout();

//

// label1

//

this.label1.location = new system.drawing.point(16, 24);

this.label1.name = "label1";

this.label1.size = new system.drawing.size(80, 23);

this.label1.tabindex = 0;

this.label1.text = "服務(wù)器地址:";

this.label1.textalign = system.drawing.contentalignment.middleright;

//

// label2

//

this.label2.location = new system.drawing.point(16, 64);

this.label2.name = "label2";

this.label2.size = new system.drawing.size(80, 23);

this.label2.tabindex = 1;

this.label2.text = "本地文件名:";

this.label2.textalign = system.drawing.contentalignment.middleright;

//

// download

//

this.download.location = new system.drawing.point(288, 24);

this.download.name = "download";

this.download.tabindex = 2;

this.download.text = "開始下載";

this.download.click += new system.eventhandler(this.download_click);

//

// serveraddress

//

this.serveraddress.location = new system.drawing.point(96, 24);

this.serveraddress.name = "serveraddress";

this.serveraddress.size = new system.drawing.size(176, 21);

this.serveraddress.tabindex = 3;

this.serveraddress.text = "";

//

// filename

//

this.filename.location = new system.drawing.point(96, 64);

this.filename.name = "filename";

this.filename.size = new system.drawing.size(176, 21);

this.filename.tabindex = 4;

this.filename.text = "";

//

// form1

//

this.autoscalebasesize = new system.drawing.size(6, 14);

this.clientsize = new system.drawing.size(376, 117);

this.controls.addrange(new system.windows.forms.control[] {

this.filename,

this.serveraddress,

this.download,

this.label2,

this.label1});

this.name = "form1";

this.text = "網(wǎng)頁下載器";

this.resumelayout(false);


}

#endregion


///

/// 應(yīng)用程序的主入口點(diǎn)。

///

[stathread]

static void main()

{

application.run(new form1());

}


private string dosocketget(string server)

{

//定義一些必要的變量以及一條要發(fā)送到服務(wù)器的字符串

encoding ascii = encoding.ascii;

string get = "get / http/1.1/r/nhost: " + server +

"/r/nconnection: close/r/n/r/n";

byte[] byteget = ascii.getbytes(get);

byte[] recvbytes = new byte[256];

string strretpage = null;


//獲取服務(wù)器相關(guān)的ip地址列表,其中第一項(xiàng)即為我們所需的

ipaddress hostadd = dns.resolve(server).addresslist[0];


//根據(jù)獲得的服務(wù)器的ip地址創(chuàng)建一個(gè)終結(jié)點(diǎn),端口為默認(rèn)的80

ipendpoint ephost = new ipendpoint(hostadd, 80);


//創(chuàng)建一個(gè)socket實(shí)例

socket s = new socket(addressfamily.internetwork, sockettype.stream,

protocoltype.tcp );


try

{

//用上面所取得的終結(jié)點(diǎn)連接到服務(wù)器

s.connect(ephost);

}

catch(exception se)

{

messagebox.show("連接錯(cuò)誤:"+se.message,"提示信息",

messageboxbuttons.retrycancel,messageboxicon.information);

}


if (!s.connected)

{

strretpage = "不能連接到服務(wù)器!";

return strretpage;

}


try

{

//向服務(wù)器發(fā)送get命令

s.send(byteget, byteget.length, socketflags.none);

}

catch(exception ce)

{

messagebox.show("發(fā)送錯(cuò)誤:"+ce.message,"提示信息",

messageboxbuttons.retrycancel,messageboxicon.information);

}


//接收頁面數(shù)據(jù),直到所有字節(jié)接收完畢

int32 bytes = s.receive(recvbytes, recvbytes.length, 0);

strretpage = "以下是在服務(wù)器" + server + "上的默認(rèn)網(wǎng)頁:/r/n";

strretpage = strretpage + ascii.getstring(recvbytes, 0, bytes);


while (bytes > 0)

{

bytes = s.receive(recvbytes, recvbytes.length, socketflags.none);

strretpage = strretpage + ascii.getstring(recvbytes, 0, bytes);

}


//禁用并關(guān)閉socket實(shí)例

s.shutdown(socketshutdown.both);

s.close();


return strretpage;

}


private void download_click(object sender, system.eventargs e)

{

//將所讀取的字符串轉(zhuǎn)換為字節(jié)數(shù)組

byte[] content=encoding.ascii.getbytes(dosocketget(serveraddress.text));

try

{

//創(chuàng)建文件流對象實(shí)例

filestream fs=new filestream(filename.text,filemode.openorcreate,fileaccess.readwrite);

//寫入文件

fs.write(content,0,content.length);

}

catch(exception fe)

{

messagebox.show("文件創(chuàng)建/寫入錯(cuò)誤:"+fe.message,"提示信息",messageboxbuttons.retrycancel,messageboxicon.information);

}

}

}

}


以上程序在windows 2000服務(wù)器版、visual studio.net中文正式版下調(diào)試通過


發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 昆明市| 永胜县| 罗田县| 石楼县| 和田市| 洪江市| 伊宁县| 新闻| 高要市| 比如县| 盘锦市| 清河县| 成武县| 宁海县| 白水县| 青铜峡市| 许昌县| 遵义市| 天水市| 紫阳县| 错那县| 宜都市| 洛阳市| 科尔| 沈丘县| 苍南县| 巴里| 炎陵县| 天水市| 吉水县| 和田市| 绥化市| 新安县| 电白县| 义乌市| 淮阳县| 武鸣县| 磴口县| 大足县| 依兰县| 绍兴县|