每次編寫(xiě)設(shè)計(jì)網(wǎng)絡(luò)通訊程序時(shí),總面對(duì)一個(gè)問(wèn)題,就是要自定義一組應(yīng)用協(xié)議(即通訊協(xié)議),然后再寫(xiě)相應(yīng)的方法來(lái)解析協(xié)議,并提供相應(yīng)的接口供上層調(diào)用 。假如只是簡(jiǎn)單的文本信息通訊還輕易,但要交換一些控制信息或結(jié)構(gòu)復(fù)雜的數(shù)據(jù)時(shí),比如做聯(lián)機(jī)游戲,更是讓人頭疼 。
最近忽然想到一個(gè)點(diǎn)子,可以用對(duì)象串行化技術(shù)將對(duì)象直接轉(zhuǎn)換為二進(jìn)制數(shù)據(jù)發(fā)送,然后接收時(shí)直接還原為對(duì)象 。具體過(guò)程是,將要發(fā)送的數(shù)據(jù)放在一個(gè)HashTable中,串行化后發(fā)送出去,在接收方接收到數(shù)據(jù)并還原為HashTable,根據(jù)預(yù)先約定好的Key和獲取自己關(guān)心的數(shù)據(jù) 。在這種情況下,定義通訊協(xié)議的內(nèi)容實(shí)質(zhì)上也就只是指定一組Key就行了 。再也不用做那些規(guī)定第幾個(gè)字段是什么類(lèi)型有多長(zhǎng)的煩躁的事情了 。
可能很多人很善于用XML,也將之廣泛用于網(wǎng)絡(luò)通訊 。XML有不可比擬的好處,因?yàn)樗峭脚_(tái)無(wú)關(guān)的,而且基本上任何開(kāi)發(fā)語(yǔ)言都有現(xiàn)成庫(kù)來(lái)解析XML 。這個(gè)和我的觀點(diǎn)并不沖突 。對(duì)象串行化并不局限于二進(jìn)制數(shù)據(jù) 。C#里有豐富的方法,可以將對(duì)象串行化為XML文檔,也支持用SOAP協(xié)議來(lái)串行化數(shù)據(jù) 。所以只要用公共的串行化標(biāo)準(zhǔn)來(lái)串行化對(duì)象,也可以達(dá)到跨平臺(tái)、跨語(yǔ)言的目的 。其實(shí)現(xiàn)在流行的Web Service其核心技術(shù)也就大概是這樣吧 。
原理說(shuō)完了,貼段代碼做個(gè)例子 。ObjectTransferClient(簡(jiǎn)稱(chēng)OTC)是一個(gè)利用UDP協(xié)議及二進(jìn)制對(duì)象串行化的包括對(duì)象發(fā)送和接收的庫(kù) 。調(diào)用方法很簡(jiǎn)單,用Send發(fā)送對(duì)象,響應(yīng)ReceiveObject事件來(lái)處理接收的對(duì)象 。至于具體細(xì)節(jié)就不多敘述了,相信有一定C#基礎(chǔ)的人能輕松看懂的 。
這一原理的應(yīng)用潛力是巨大的,我在這里拋磚引玉,還請(qǐng)指教 。
using System;
using System.Net.Sockets;
using System.Net;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading;
namespace OTC
{
///
/// 對(duì)象傳送器,使用UDP協(xié)議通過(guò)網(wǎng)路在不同主機(jī)間傳送對(duì)象 。
///
public class ObjectTransferClient : IDisposable
{
private Thread ListenThread;
private BinaryFormatter Serializer = new BinaryFormatter();
private int m_Port;
private UdpClient m_Client;
private bool m_IsStart;
private bool m_IsConnected;
///
/// 接收到對(duì)象事件
///
public event ReceiveObjectEventHandler ReceiveObject;
///
/// 構(gòu)建一個(gè)對(duì)象傳送器,默認(rèn)端口7321
///
public ObjectTransferClient() : this(7321)
{
//
// TODO: 在此處添加構(gòu)造函數(shù)邏輯
//
}
///
/// 指定端口號(hào)構(gòu)建一個(gè)對(duì)象傳送器 。
///
/// 端口號(hào)
public ObjectTransferClient(int port)
{
this.m_Port = port;
this.m_IsConnected = false;
this.m_IsStart = false;
}
///
/// 初始化傳送器并開(kāi)始工作
///
public void Start()
{
if (!this.m_IsStart)
{
this.m_Client = new UdpClient(this.m_Port);
ListenThread = new Thread(new ThreadStart(this.Listen));
ListenThread.Start();
this.m_IsStart = true;
}
}
///
/// 使用指定的主機(jī)名和端口連接默認(rèn)的遠(yuǎn)程主機(jī)
///
/// 主機(jī)名
/// 端口
public void Connect(string hostname, int port)
{
this.m_Client.Connect(hostname, port);
}
///
/// 使用指定的IP地址和端口連接默認(rèn)的遠(yuǎn)程主機(jī)
///
/// IP地址
/// 端口
public void Connect(IPAddress ipaddress, int port)
{
this.m_Client.Connect(ipaddress, port);
}
///
/// 使用網(wǎng)絡(luò)終結(jié)點(diǎn)連接默認(rèn)的遠(yuǎn)程主機(jī)
推薦閱讀
- InfoPath輕松制作office2003各種表單
- 教你如何將自己的手機(jī)號(hào)變成空號(hào)
- 別人的淘寶號(hào)可以綁自己的支付寶嗎
- 酸堿鹽的定義 酸堿鹽的定義和區(qū)分方法
- 你要如何實(shí)現(xiàn)自己的夢(mèng)想寫(xiě)一段話(huà)
- 三代以?xún)?nèi)旁系血親如何定義
- WPS2013文字加上自己的版權(quán)聲明
- 諾基亞 8800D,N76入手 寫(xiě)些自己的感覺(jué)
- 手機(jī)bilibili怎么查看自己的評(píng)論
- 什么是整數(shù) 整數(shù)的定義
