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

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

續(xù)實例解析SOCKET編程模型之異步通信篇(下)

2024-07-21 02:23:36
字體:
來源:轉載
供稿:網(wǎng)友
異步客戶端套接字在等待網(wǎng)絡操作完成時不掛起應用程序。相反,它使用標準 .net framework 異步編程模型在一個線程上處理網(wǎng)絡連接,而應用程序繼續(xù)在原始線程上運行。異步套接字適用于大量使用網(wǎng)絡或不能等待網(wǎng)絡操作完成才能繼續(xù)的應用程序。

socket 類遵循異步方法的 .net framework 命名模式;例如,同步 receive 方法對應異步 beginreceive 和 endreceive 方法。

異步操作要求回調方法返回操作結果。如果應用程序不需要知道結果,則不需要任何回調方法。本節(jié)中的代碼示例闡釋如何使用某個方法開始與網(wǎng)絡設備的連接并使用回調方法結束連接,如何使用某個方法開始發(fā)送數(shù)據(jù)并使用回調方法完成發(fā)送,以及如何使用某個方法開始接收數(shù)據(jù)并使用回調方法結束接收數(shù)據(jù)。

異步套接字使用多個系統(tǒng)線程池中的線程處理網(wǎng)絡連接。一個線程負責初始化數(shù)據(jù)的發(fā)送或接收;其他線程完成與網(wǎng)絡設備的連接并發(fā)送或接收數(shù)據(jù)。在程序源碼中,system.threading.manualresetevent 類的實例用于掛起主線程的執(zhí)行并在執(zhí)行可以繼續(xù)時發(fā)出信號。

在客戶端源碼中,為了將異步套接字連接到網(wǎng)絡設備,socket 方法初始化一個 socket,然后調用 beginconnect 方法,傳遞表示網(wǎng)絡設備的遠程終結點、連接回調方法以及狀態(tài)對象(即客戶端 socket,用于在異步調用之間傳遞狀態(tài)信息)。該示例實現(xiàn) connect 方法以將指定的 socket 連接到指定的終結點。它采用一個名為 connectdone 的全局 manualresetevent: public iasyncresult beginconnect(
endpoint remoteep,
asynccallback callback,
object state
);

連接回調方法 connectcallback 實現(xiàn) asynccallback 委托。它在遠程設備可用時連接到遠程設備,然后通過設置 manualresetevent connectdone 向應用程序線程發(fā)出連接完成的信號。下面的客戶端源碼中實現(xiàn)了 connectcallback 方法。

send 示例方法以 ascii 格式對指定的字符串數(shù)據(jù)進行編碼,并將其異步發(fā)送到指定的套接字所表示的網(wǎng)絡設備。

發(fā)送回調方法 sendcallback 實現(xiàn) asynccallback 委托。它在網(wǎng)絡設備準備接收時發(fā)送數(shù)據(jù)。下面的源碼中實現(xiàn)了 sendcallback 方法。它采用一個名為 senddone 的全局 manualresetevent。

從客戶端套接字讀取數(shù)據(jù)需要一個在異步調用之間傳遞值的狀態(tài)對象。下面的類是用于從客戶端套接字接收數(shù)據(jù)的示例狀態(tài)對象。它包含以下各項的字段:客戶端套接字,用于接收數(shù)據(jù)的緩沖區(qū),以及用于保存?zhèn)魅霐?shù)據(jù)字符串的 stringbuilder。將這些字段放在該狀態(tài)對象中,使這些字段的值在多個調用之間得以保留,以便從客戶端套接字讀取數(shù)據(jù)。

public class stateobject {
// client socket.
public socket worksocket = null;
// size of receive buffer.
public const int buffersize = 256;
// receive buffer.
public byte[] buffer = new byte[buffersize];
// received data string.
public stringbuilder sb = new stringbuilder();
} //為簡單起見,客戶端源碼中并未創(chuàng)建此類

receive 方法示例設置狀態(tài)對象,然后調用 beginreceive 方法從客戶端套接字異步讀取數(shù)據(jù)。

接收回調方法 receivecallback 實現(xiàn) asynccallback 委托。它接收來自網(wǎng)絡設備的數(shù)據(jù)并生成消息字符串。它將來自網(wǎng)絡的一個或多個數(shù)據(jù)字節(jié)讀入數(shù)據(jù)緩沖區(qū),然后再次調用 beginreceive 方法,直到客戶端發(fā)送的數(shù)據(jù)完成為止。從客戶端讀取所有數(shù)據(jù)后,receivecallback 通過設置 manualresetevent senddone 向應用程序線程發(fā)出數(shù)據(jù)完成的信號。

//以下是客戶端詳細實現(xiàn)代碼

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.threading;
using system.text;
namespace 聊天_socket_client
{
/// <summary>
/// form1 的摘要說明。
/// </summary>
public class form1 : system.windows.forms.form
{
private system.windows.forms.label label4;
private system.windows.forms.label label3;
private system.windows.forms.label label2;
private system.windows.forms.label label1;
private system.windows.forms.button btnstop;
private system.windows.forms.button btnsend;
private system.windows.forms.textbox txtport;
private system.windows.forms.textbox txtserver;
private system.windows.forms.richtextbox rtbsend;
private system.windows.forms.richtextbox rtbreceive;
private system.windows.forms.statusbar statusbar1;
private system.windows.forms.button btnconnect;
private ipaddress hostipaddress;
private ipendpoint server;
private socket sock;
private const int buffersize=256;
private byte[] buffer=new byte[buffersize];
private static manualresetevent connectdone=new manualresetevent(false);
private static manualresetevent senddone=new manualresetevent(false);
/// <summary>
/// 必需的設計器變量。
/// </summary>
private system.componentmodel.container components = null;

public form1()
{
//
// windows 窗體設計器支持所必需的
//
initializecomponent();

//
// todo: 在 initializecomponent 調用后添加任何構造函數(shù)代碼
//
}

/// <summary>
/// 清理所有正在使用的資源。
/// </summary>
protected override void dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.dispose();
}
}
base.dispose( disposing );
}

#region windows 窗體設計器生成的代碼
/// <summary>
/// 設計器支持所需的方法 - 不要使用代碼編輯器修改
/// 此方法的內(nèi)容。
/// </summary>
private void initializecomponent()
{
this.label4 = new system.windows.forms.label();
this.label3 = new system.windows.forms.label();
this.label2 = new system.windows.forms.label();
this.label1 = new system.windows.forms.label();
this.btnstop = new system.windows.forms.button();
this.btnsend = new system.windows.forms.button();
this.btnconnect = new system.windows.forms.button();
this.txtport = new system.windows.forms.textbox();
this.txtserver = new system.windows.forms.textbox();
this.rtbsend = new system.windows.forms.richtextbox();
this.rtbreceive = new system.windows.forms.richtextbox();
this.statusbar1 = new system.windows.forms.statusbar();
this.suspendlayout();
//
// label4
//
this.label4.location = new system.drawing.point(16, 152);
this.label4.name = "label4";
this.label4.size = new system.drawing.size(64, 23);
this.label4.tabindex = 22;
this.label4.text = "發(fā)送信息:";
//
// label3
//
this.label3.location = new system.drawing.point(16, 64);
this.label3.name = "label3";
this.label3.size = new system.drawing.size(64, 23);
this.label3.tabindex = 21;
this.label3.text = "接收信息:";
//
// label2
//
this.label2.location = new system.drawing.point(216, 16);
this.label2.name = "label2";
this.label2.size = new system.drawing.size(64, 23);
this.label2.tabindex = 20;
this.label2.text = "監(jiān)聽端口:";
//
// label1
//
this.label1.location = new system.drawing.point(16, 16);
this.label1.name = "label1";
this.label1.size = new system.drawing.size(56, 23);
this.label1.tabindex = 19;
this.label1.text = "服務器:";
//
// btnstop
//
this.btnstop.location = new system.drawing.point(256, 256);
this.btnstop.name = "btnstop";
this.btnstop.tabindex = 18;
this.btnstop.text = "關閉連接";
this.btnstop.click += new system.eventhandler(this.btnstop_click);
//
// btnsend
//
this.btnsend.location = new system.drawing.point(144, 256);
this.btnsend.name = "btnsend";
this.btnsend.tabindex = 17;
this.btnsend.text = "發(fā)送信息";
this.btnsend.click += new system.eventhandler(this.btnsend_click);
//
// btnconnect
//
this.btnconnect.location = new system.drawing.point(32, 256);
this.btnconnect.name = "btnconnect";
this.btnconnect.tabindex = 16;
this.btnconnect.text = "請求連接";
this.btnconnect.click += new system.eventhandler(this.btnconnect_click);
//
// txtport
//
this.txtport.location = new system.drawing.point(288, 16);
this.txtport.name = "txtport";
this.txtport.size = new system.drawing.size(48, 21);
this.txtport.tabindex = 15;
this.txtport.text = "19811";
//
// txtserver
//
this.txtserver.location = new system.drawing.point(72, 16);
this.txtserver.name = "txtserver";
this.txtserver.tabindex = 14;
this.txtserver.text = "127.0.0.1";
//
// rtbsend
//
this.rtbsend.location = new system.drawing.point(80, 152);
this.rtbsend.name = "rtbsend";
this.rtbsend.size = new system.drawing.size(264, 96);
this.rtbsend.tabindex = 13;
this.rtbsend.text = "";
//
// rtbreceive
//
this.rtbreceive.location = new system.drawing.point(80, 56);
this.rtbreceive.name = "rtbreceive";
this.rtbreceive.size = new system.drawing.size(264, 96);
this.rtbreceive.tabindex = 12;
this.rtbreceive.text = "";
//
// statusbar1
//
this.statusbar1.location = new system.drawing.point(0, 287);
this.statusbar1.name = "statusbar1";
this.statusbar1.showpanels = true;
this.statusbar1.size = new system.drawing.size(360, 22);
this.statusbar1.tabindex = 23;
this.statusbar1.text = "statusbar1";
//
// form1
//
this.autoscalebasesize = new system.drawing.size(6, 14);
this.clientsize = new system.drawing.size(360, 309);
this.controls.add(this.statusbar1);
this.controls.add(this.label4);
this.controls.add(this.label3);
this.controls.add(this.label2);
this.controls.add(this.label1);
this.controls.add(this.btnstop);
this.controls.add(this.btnsend);
this.controls.add(this.btnconnect);
this.controls.add(this.txtport);
this.controls.add(this.txtserver);
this.controls.add(this.rtbsend);
this.controls.add(this.rtbreceive);
this.name = "form1";
this.text = "聊天程序-客戶端";
this.closing += new system.componentmodel.canceleventhandler(this.form1_closing);
this.resumelayout(false);

}
#endregion

/// <summary>
/// 應用程序的主入口點。
/// </summary>
[stathread]
static void main()
{
application.run(new form1());
}

private void btnconnect_click(object sender, system.eventargs e)
{
try
{
hostipaddress=ipaddress.parse(txtserver.text);
}
catch{messagebox.show("請輸入正確的ip地址格式。");}
try
{
server=new ipendpoint(hostipaddress,int32.parse(txtport.text));
sock=new socket(addressfamily.internetwork,sockettype.stream,protocoltype.tcp);
sock.beginconnect(server,new asynccallback(connectcallback),sock);
}
catch(exception ee){messagebox.show(ee.message);}
}
private void connectcallback(iasyncresult ar)
{
try
{
socket client=(socket)ar.asyncstate; //獲取狀態(tài)
client.endconnect(ar);
try
{
byte[] bytedata=encoding.bigendianunicode.getbytes("準備完畢,可以通話"+"/r/n");
sock.beginsend(bytedata,0,bytedata.length,0,new asynccallback(sendcallback),sock);
}
catch(exception ee){messagebox.show(ee.message);}
statusbar1.text="與主機"+txtserver.text+"端口"+txtport.text+"連接成功";
thread thread=new thread(new threadstart(threadproc));
thread.start(); //開始接收數(shù)據(jù)線程
connectdone.set(); //將指定事件的狀態(tài)設置為終止。
}
catch{}
}
private void sendcallback(iasyncresult ar)
{
try{
socket client=(socket)ar.asyncstate;
senddone.set();
}
catch(exception ee){messagebox.show(ee.message);}
}
private void threadproc()
{
try
{
sock.beginreceive(buffer,0,buffersize,0,new asynccallback(receivecallback),sock);
}
catch(exception ee){messagebox.show(ee.message);}
}
private void receivecallback(iasyncresult ar)
{
try
{
socket client=(socket)ar.asyncstate;
int bytesread=client.endreceive(ar);//結束掛起的異步讀取。返回接收到的字節(jié)數(shù)。
stringbuilder sb=new stringbuilder();
sb.append(encoding.bigendianunicode.getstring(buffer,0,bytesread));//儲存數(shù)據(jù)
string content=sb.tostring(); //轉換為字符串
sb.remove(0,content.length); //清除sb內(nèi)容
rtbreceive.appendtext(content+"/r/n");
client.beginreceive(buffer,0,buffersize,0,new asynccallback(receivecallback),client);
}
catch{}
}

private void btnsend_click(object sender, system.eventargs e)
{
try
{
string strsend ="client--->"+rtbsend.text+"/r/n";
byte[] bytesend = encoding.bigendianunicode.getbytes(strsend);
sock.beginsend(bytesend,0,bytesend.length,0,new asynccallback(sendcallback),sock);
}
catch{messagebox.show("連接尚未建立,無法發(fā)送.");}
}

private void btnstop_click(object sender, system.eventargs e)
{
try
{
sock.close();
statusbar1.text="與主機"+txtserver.text+"端口"+txtport.text+"斷開連接";
}
catch{messagebox.show("連接尚未建立,關閉無效");}
}

private void form1_closing(object sender, system.componentmodel.canceleventargs e)
{
try
{
sock.close();
}
catch{}
}
}
}

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 穆棱市| 天气| 青川县| 东乌| 崇义县| 涞水县| 昌吉市| 剑河县| 卫辉市| 静宁县| 顺昌县| 江油市| 苗栗县| 五峰| 彰化市| 邵东县| 鄢陵县| 武川县| 迭部县| 林甸县| 云林县| 桐柏县| 麦盖提县| 聊城市| 廊坊市| 安义县| 广汉市| 琼海市| 陇川县| 买车| 大埔区| 方山县| 阿勒泰市| 乳源| 余江县| 江永县| 琼海市| 容城县| 濉溪县| 阳山县| 板桥市|