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

首頁 > 編程 > .NET > 正文

C#.Net網(wǎng)絡程序開發(fā)-Socket篇

2024-07-10 13:00:19
字體:
來源:轉載
供稿:網(wǎng)友
菜鳥學堂:
microsoft.net framework為應用程序訪問internet提供了分層的、可擴展的以及受管轄的網(wǎng)絡服務,其名字空間system.net和system.net.sockets包含豐富的類可以開發(fā)多種網(wǎng)絡應用程序。.net類采用的分層結構允許應用程序在不同的控制級別上訪問網(wǎng)絡,開發(fā)人員可以根據(jù)需要選擇針對不同的級別編制程序,這些級別幾乎囊括了internet的所有需要--從socket套接字到普通的請求/響應,更重要的是,這種分層是可以擴展的,能夠適應internet不斷擴展的需要。

拋開iso/osi模型的7層構架,單從tcp/ip模型上的邏輯層面上看,.net類可以視為包含3個層次:請求/響應層、應用協(xié)議層、傳輸層。webreqeust和webresponse 代表了請求/響應層,支持http、tcp和udp的類組成了應用協(xié)議層,而socket類處于傳輸層。

傳輸層位于這個結構的最底層,當其上面的應用協(xié)議層和請求/響應層不能滿足應用程序的特殊需要時,就需要使用這一層進行socket套接字編程。

而在.net中,system.net.sockets 命名空間為需要嚴密控制網(wǎng)絡訪問的開發(fā)人員提供了 windows sockets (winsock) 接口的托管實現(xiàn)。system.net 命名空間中的所有其他網(wǎng)絡訪問類都建立在該套接字socket實現(xiàn)之上,如tcpclient、tcplistener 和 udpclient 類封裝有關創(chuàng)建到 internet 的 tcp 和 udp 連接的詳細信息;networkstream類則提供用于網(wǎng)絡訪問的基礎數(shù)據(jù)流等,常見的許多internet服務都可以見到socket的蹤影,如telnet、http、email、echo等,這些服務盡管通訊協(xié)議protocol的定義不同,但是其基礎的傳輸都是采用的socket。

其實,socket可以象流stream一樣被視為一個數(shù)據(jù)通道,這個通道架設在應用程序端(客戶端)和遠程服務器端之間,而后,數(shù)據(jù)的讀取(接收)和寫入(發(fā)送)均針對這個通道來進行。

可見,在應用程序端或者服務器端創(chuàng)建了socket對象之后,就可以使用send/sentto方法將數(shù)據(jù)發(fā)送到連接的socket,或者使用receive/receivefrom方法接收來自連接socket的數(shù)據(jù);

針對socket編程,.net 框架的 socket 類是 winsock32 api 提供的套接字服務的托管代碼版本。其中為實現(xiàn)網(wǎng)絡編程提供了大量的方法,大多數(shù)情況下,socket 類方法只是將數(shù)據(jù)封送到它們的本機 win32 副本中并處理任何必要的安全檢查。如果你熟悉winsock api函數(shù),那么用socket類編寫網(wǎng)絡程序會非常容易,當然,如果你不曾接觸過,也不會太困難,跟隨下面的解說,你會發(fā)覺使用socket類開發(fā)windows 網(wǎng)絡應用程序原來有規(guī)可尋,它們在大多數(shù)情況下遵循大致相同的步驟。

在使用之前,你需要首先創(chuàng)建socket對象的實例,這可以通過socket類的構造方法來實現(xiàn):

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


其中,addressfamily 參數(shù)指定 socket 使用的尋址方案,sockettype 參數(shù)指定 socket 的類型,protocoltype 參數(shù)指定 socket 使用的協(xié)議。

下面的示例語句創(chuàng)建一個 socket,它可用于在基于 tcp/ip 的網(wǎng)絡(如 internet)上通訊。

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


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

socket s = new socket(addressfamily.internetwork, sockettype.dgram, protocoltype.udp);


一旦創(chuàng)建 socket,在客戶端,你將可以通過connect方法連接到指定的服務器,并通過send/sendto方法向遠程服務器發(fā)送數(shù)據(jù),而后可以通過receive/receivefrom從服務端接收數(shù)據(jù);而在服務器端,你需要使用bind方法綁定所指定的接口使socket與一個本地終結點相聯(lián),并通過listen方法偵聽該接口上的請求,當偵聽到用戶端的連接時,調(diào)用accept完成連接的操作,創(chuàng)建新的socket以處理傳入的連接請求。使用完 socket 后,記住使用 shutdown 方法禁用 socket,并使用 close 方法關閉 socket。其間用到的方法/函數(shù)有:

socket.connect方法:建立到遠程設備的連接
public void connect(endpoint remoteep)(有重載方法)
socket.send 方法:從數(shù)據(jù)中的指示位置開始將數(shù)據(jù)發(fā)送到連接的 socket。
public int send(byte[], int, socketflags);(有重載方法)
socket.sendto 方法 將數(shù)據(jù)發(fā)送到特定終結點。
public int sendto(byte[], endpoint);(有重載方法)
socket.receive方法:將數(shù)據(jù)從連接的 socket 接收到接收緩沖區(qū)的特定位置。
public int receive(byte[],int,socketflags);
socket.receivefrom方法:接收數(shù)據(jù)緩沖區(qū)中特定位置的數(shù)據(jù)并存儲終結點。
public int receivefrom(byte[], int, socketflags, ref endpoint);
socket.bind 方法:使 socket 與一個本地終結點相關聯(lián):
public void bind( endpoint localep );
socket.listen方法:將 socket 置于偵聽狀態(tài)。
public void listen( int backlog );
socket.accept方法:創(chuàng)建新的 socket 以處理傳入的連接請求。
public socket accept();
socket.shutdown方法:禁用某 socket 上的發(fā)送和接收
public void shutdown( socketshutdown how );
socket.close方法:強制 socket 連接關閉
public void close();


可以看出,以上許多方法包含endpoint類型的參數(shù),在internet中,tcp/ip 使用一個網(wǎng)絡地址和一個服務端口號來唯一標識設備。網(wǎng)絡地址標識網(wǎng)絡上的特定設備;端口號標識要連接到的該設備上的特定服務。網(wǎng)絡地址和服務端口的組合稱為終結點,在 .net 框架中正是由 endpoint 類表示這個終結點,它提供表示網(wǎng)絡資源或服務的抽象,用以標志網(wǎng)絡地址等信息。.net同時也為每個受支持的地址族定義了 endpoint 的子代;對于 ip 地址族,該類為 ipendpoint。ipendpoint 類包含應用程序連接到主機上的服務所需的主機和端口信息,通過組合服務的主機ip地址和端口號,ipendpoint 類形成到服務的連接點。

用到ipendpoint類的時候就不可避免地涉及到計算機ip地址,.net中有兩種類可以得到ip地址實例:

ipaddress類:ipaddress 類包含計算機在 ip 網(wǎng)絡上的地址。其parse方法可將 ip 地址字符串轉換為 ipaddress 實例。下面的語句創(chuàng)建一個 ipaddress 實例:

ipaddress myip = ipaddress.parse("192.168.1.2");


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

iphostentry iphostinfo = dns.resolve("host.contoso.com");
ipaddress ipaddress = iphostinfo.addresslist[0];


你也可以使用gethostname方法得到iphostentry實例:

iphosntentry hostinfo=dns.gethostbyname("host.contoso.com")


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

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

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

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

在掌握上面得知識后,下面的代碼將該服務器主機( host.contoso.com的 ip 地址與端口號組合,以便為連接創(chuàng)建遠程終結點:

ipendpoint ipe = new ipendpoint(ipaddress,11000);


確定了遠程設備的地址并選擇了用于連接的端口后,應用程序可以嘗試建立與遠程設備的連接。下面的示例使用現(xiàn)有的 ipendpoint 實例與遠程設備連接,并捕獲可能引發(fā)的異常:

try {
s.connect(ipe);//嘗試連接
}
//處理參數(shù)為空引用異常
catch(argumentnullexception ae) {
console.writeline("argumentnullexception : {0}", ae.tostring());
}
//處理操作系統(tǒng)異常
catch(socketexception se) {
console.writeline("socketexception : {0}", se.tostring());
}
catch(exception e) {
console.writeline("unexpected exception : {0}", e.tostring());
}


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

另外,很多時候,socket編程視情況不同需要在客戶端和服務器端分別予以實現(xiàn),在客戶端編制應用程序向服務端指定端口發(fā)送請求,同時編制服務端應用程序處理該請求,這個過程在上面的闡述中已經(jīng)提及;當然,并非所有的socket編程都需要你嚴格編寫這兩端程序;視應用情況不同,你可以在客戶端構造出請求字符串,服務器相應端口捕獲這個請求,交由其公用服務程序進行處理。以下事例語句中的字符串就向遠程主機提出頁面請求:

string get = "get / http/1.1/r/nhost: " + server + "/r/nconnection: close/r/n/r/n";


遠程主機指定端口接受到這一請求后,就可利用其公用服務程序進行處理而不需要另行編制服務器端應用程序。

綜合運用以上闡述的使用visual c#進行socket網(wǎng)絡程序開發(fā)的知識,下面的程序段完整地實現(xiàn)了web頁面下載功能。用戶只需在窗體上輸入遠程主機名(dns 主機名或以點分隔的四部分表示法格式的 ip 地址)和預保存的本地文件名,并利用專門提供http服務的80端口,就可以獲取遠程主機頁面并保存在本地機指定文件中。如果保存格式是.htm格式,你就可以在internet瀏覽器中打開該頁面。適當添加代碼,你甚至可以實現(xiàn)一個簡單的瀏覽器程序。


實現(xiàn)此功能的主要源代碼如下:

//"開始"按鈕事件
private void button1_click(object sender, system.eventargs e) {
//取得預保存的文件名
string filename=textbox3.text.trim();
//遠程主機
string hostname=textbox1.text.trim();
//端口
int port=int32.parse(textbox2.text.trim());
//得到主機信息
iphostentry ipinfo=dns.gethostbyname(hostname);
//取得ipaddress[]
ipaddress[] ipaddr=ipinfo.addresslist;
//得到ip
ipaddress ip=ipaddr[0];
//組合出遠程終結點
ipendpoint hostep=new ipendpoint(ip,port);
//創(chuàng)建socket 實例
socket socket=new socket(addressfamily.internetwork,sockettype.stream,protocoltype.tcp);
try
{
//嘗試連接
socket.connect(hostep);
}
catch(exception se)
{
messagebox.show("連接錯誤"+se.message,"提示信息
,messageboxbuttons.retrycancel,messageboxicon.information);
}
//發(fā)送給遠程主機的請求內(nèi)容串
string sendstr="get / http/1.1/r/nhost: " + hostname +
"/r/nconnection: close/r/n/r/n";
//創(chuàng)建bytes字節(jié)數(shù)組以轉換發(fā)送串
byte[] bytessendstr=new byte[1024];
//將發(fā)送內(nèi)容字符串轉換成字節(jié)byte數(shù)組
bytessendstr=encoding.ascii.getbytes(sendstr);
try
{
//向主機發(fā)送請求
socket.send(bytessendstr,bytessendstr.length,0);
}
catch(exception ce)
{
messagebox.show("發(fā)送錯誤:"+ce.message,"提示信息
,messageboxbuttons.retrycancel,messageboxicon.information);
}
//聲明接收返回內(nèi)容的字符串
string recvstr="";
//聲明字節(jié)數(shù)組,一次接收數(shù)據(jù)的長度為1024字節(jié)
byte[] recvbytes=new byte[1024];
//返回實際接收內(nèi)容的字節(jié)數(shù)
int bytes=0;
//循環(huán)讀取,直到接收完所有數(shù)據(jù)
while(true)
{
bytes=socket.receive(recvbytes,recvbytes.length,0);
//讀取完成后退出循環(huán)
if(bytes〈=0)
break;
//將讀取的字節(jié)數(shù)轉換為字符串
recvstr+=encoding.ascii.getstring(recvbytes,0,bytes);
}
//將所讀取的字符串轉換為字節(jié)數(shù)組
byte[] content=encoding.ascii.getbytes(recvstr);
try
{
//創(chuàng)建文件流對象實例
filestream fs=new filestream(filename,filemode.openorcreate,fileaccess.readwrite);
//寫入文件
fs.write(content,0,content.length);
}
catch(exception fe)
{
messagebox.show("文件創(chuàng)建/寫入錯誤:"+fe.message,"提示信息",messageboxbuttons.retrycancel,messageboxicon.information);
}
//禁用socket
socket.shutdown(socketshutdown.both);
//關閉socket
socket.close();
}
}


程序在windowsxp中文版、.net framework 中文正式版、visual studio.net中文正式版下調(diào)試通過
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 康定县| 阿拉善右旗| 高要市| 乳山市| 中超| 武山县| 梁河县| 夏邑县| 体育| 石嘴山市| 海晏县| 泸州市| 太白县| 虎林市| 吴桥县| 临猗县| 阿拉善左旗| 峨边| 时尚| 八宿县| 永新县| 肃南| 彭泽县| 兴海县| 巨鹿县| 浮梁县| 井研县| 麦盖提县| 罗源县| 汉阴县| 韶关市| 昭平县| 柞水县| 仪陇县| 南阳市| 成武县| 浙江省| 杂多县| 临颍县| 峨山| 视频|