数据传输是个很大的概念。我不是从理论的角度去记录随笔,只是把互联传输中的概念简化到消息的位面。以便于对分布传输中的消息进行一下剖析,加深印象。
对处于脱机状态下的终端来说,数据的传输可以通过中间介质进行中介传输。但在联机情况下,可以不必通过第三方的介入,仅用的就是其中的数据线。这个概念很容易理解:
1 一块干电池,两根导线,一个直流电灯泡。电池和灯泡可以看做是脱机情况下的两个终端,而电流就是数据。当两者相连,电灯泡就能亮(一切状态假设成立)。两者相连就能有电流通过,这个原理是懂的。因为电压的原因,电流会有一个完整的回路。(更深的不探讨)。这里互联的两上终端如果要有电流的传输,那么至少两个必要的因素:数据线和电压。
2 在农村浇灌庄稼地。主要的步骤是:拉电闸,抽水机把地下水抽上来,然后由垄沟把水导到地里进行灌溉。这里也是有必要的因素:水泵叫水,因为水压的原因使水向前流,有通到地里的垄沟。
联机中的终端要进行数据传输要有一些必要的条件,例如其中的通道,使数据进行传输的动力等等。
协议是什么?
(引百度知道)在计算机范畴内:计算机通信网是由许多具有信息交换和处理能力的节点互连而成的,要使整个网络有条不紊地工作,就要求每个节点必须遵守一些事先约定好的有关数据格式及时序等的规则。 这些为实现网络数据交换而建立的规则、约定或标准就称为网络协议。
协议是通信双方为了实现通信而设计的约定或通话规则。
协议总是指某一层的协议。准确地说,它是在同等层之间的实体通信时,有关通信规则和约定的集合就是该层协议,例如物理层协议、传输层协议、应用层协议。
其实从字面上,我们都能理解所谓的协议是什么,这种意义对计算机通信而言也是有意义的。平常所熟知的协议有Http,Tcp/Ip,UDP等。协议是要对通信双方都有效的约定,而双方也都要符合这种约定,不管是软件环境还是硬件环境。
数据传输
计算机通信为的就是数据传输,但数据有所有同,从物理上都是二进制或者说最终在物理介质上都是二进制。
在局域网内,文件共享,打印机共享是最常见的。广域网中,电子邮件,实时通信,网页预览,资源下载,Ftp上传等。
它们的终端都要遵守共同的约定。
如果现在A和B要进行数据传输,例如A要把自己的客户名单传输到B上,
那么能过Http协议:
B架设网站服务器来发布Html,A通过http来访问B网站上的客户名单导入页,然后导入自己的客户名单并提交,数据通过Http协议Post或Get方式把数据传送到B,B在收到数据后进行存储
在Tcp/Ip协议下:
B建立套接字监听地址和端口,A与B建立连接,然后向B传递数据,B收到数据后进行存储。
而http协议中传输的是http协议包,包中包含着传递的数据,tcp协议中传输的tcp包,可能只是一个字符串。
(1)通过Socket传递字符串
服务端:
static void Main(string[] args)
{
IPAddress address = IPAddress.Parse("192.168.1.98");
IPEndPoint _address = new IPEndPoint(address, 65000);
Socket socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
socket.Bind(_address);
socket.Listen(20);
byte[] bb=new byte[255];
while (true)
{
Socket ss = socket.Accept();
ss.Receive(bb);
Console.WriteLine(Encoding.UTF8.GetString(bb));
}
}
客户端:
public void TestSocket()
{
IPAddress address = IPAddress.Parse("192.168.1.98");
IPEndPoint _address = new IPEndPoint(address,65000);
Socket socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
socket.Connect(_address);
string strMessage = "test123";
byte[] bb = Encoding.UTF8.GetBytes(strMessage);
socket.Send(bb);
Console.WriteLine("Sent: {0}", strMessage);
}
这里传递的是最简单的字符串。
在两端进行图片传递也可以参考消息(1)中的内容来实现。
(2)传递客户信息
对于传递客户信息,这里的方法就是转换为字串,转换为可解析的字串,例如json。这里通过json.net这个第三方json序列化和反序列化工具来实现对客户信息的序列化及反序列化。
服务端:
IPAddress address = IPAddress.Parse("127.0.0.1");
IPEndPoint _address = new IPEndPoint(address, 65000);
Socket socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
socket.Bind(_address);
socket.Listen(20);
byte[] bb=new byte[350];
while (true)
{
Socket ss = socket.Accept();
ss.Receive(bb);
Customer customer = new Customer();
MemoryStream ms=new MemoryStream();
ms.Read(bb,0,bb.Length);
string strJson = Encoding.Default.GetString(bb);
char c = '\0';
var p = from q in strJson where q != c select q;
char[] chs = p.ToArray<char>();
strJson = new string(chs);
try
{
customer=JsonConvert.DeserializeObject<Customer>(strJson);
}
catch
{ }
ms.Close();
Console.WriteLine(customer.Unid);
}
其中对json.net的更多内容可见官网我的博客上的几篇随笔:
http://james.newtonking.com/projects/json-net.aspx
http://www.cnblogs.com/jams742003/archive/2010/03/03/1677288.html
在客户端:
public void TestCustomer()
{
Customer customer = new Customer
{
Unid = 13,
CustomerName = "Songjiang",
CreateTime = DateTime.Now,
Telephone = new Call
{ Mobile = "1111111", FirmCall = "2222", HomeCall = "3333" }
};
string strJson = JsonConvert.SerializeObject(customer);
byte[] bb = Encoding.Default.GetBytes(strJson);
IPAddress address = IPAddress.Parse("127.0.0.1");
IPEndPoint _address = new IPEndPoint(address, 65000);
Socket socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
socket.Connect(_address);
socket.Send(bb);
Console.WriteLine("发送完毕");
socket.Close();
}
因为这个客户类的原因,使得在服务端和客户端都有有这个类。
在传递简单信息的时候,能很方便的传递,因为它们都是做为基元类型存在,但对于复杂类型,例如类类型,则要对两端都要有这个类。
在这个例子中,socket传递的包是带有一个json大串的字符串。通过抓包的工具,拿下这个包的内容是:
{"Unid": 13,"CustomerName ":"Songjiang","CreateTime":"
\/Date(1269998944484 +0800)\/","Telephone":
{"HomeCall ":"3333","Mobile ":"1111111",
"FirmCall":"2222"}}
现在有这么一种情况,在.net环境下这个数据传递是可以实现,但如果用到别的环境还能这样吗?
其实对于这个例子,它是可以的,因为json也是一种数据交换格式,是一种轻量级的。同时,可以利于机器的生成和解析。
还有一种格式就是xml格式,通过它也可以进行数据交换。这边是一个对客户信息进行xml化进行传输。
客户端:
public void TestCustomerXml()
{
Customer customer = new Customer
{
Unid = 13,
CustomerName = "Songjiang",
CreateTime = DateTime.Now,
Telephone = new Call {
Mobile = "1111111",
FirmCall = "2222",
HomeCall = "3333" }
};
//创建xml
XDocument doc = new XDocument();
doc.Add(new XElement("Customers"));
doc.Element("Customers").Add(new XElement("Customer"));
doc.Element("Customers").Element("Customer").Add(
new XElement("Unid",customer.Unid),
new XElement("CustomerName",customer.CustomerName),
new XElement("CreateTime",customer.CreateTime),
new XElement("Telephone")
);
doc.Element("Customers").Element("Customer").Element("Telephone").
Add(
new XElement("Mobile",customer.Telephone.Mobile),
new XElement("FirmCall",customer.Telephone.FirmCall),
new XElement("HomeCall",customer.Telephone.HomeCall)
);
string strXml = doc.ToString();
byte[] bb = Encoding.Default.GetBytes(strXml);
IPAddress address = IPAddress.Parse("192.168.1.105");
IPEndPoint _address = new IPEndPoint(address, 65000);
Socket socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
socket.Connect(_address);
socket.Send(bb);
Console.WriteLine("发送完毕");
socket.Close();
}
客户端创建一个描述客户数据的xml文档,然后向服务器提交。
服务端:
static void Main(string[] args)
{
IPAddress address = IPAddress.Parse("192.168.1.105");
IPEndPoint _address = new IPEndPoint(address, 65000);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(_address);
socket.Listen(20);
byte[] bb = new byte[350];
while (true)
{
Socket ss = socket.Accept();
ss.Receive(bb);
Customer customer = new Customer();
MemoryStream ms = new MemoryStream();
ms.Read(bb, 0, bb.Length);
string strXml = Encoding.Default.GetString(bb);
char c = '\0';
var p1 = from q in strXml where q != c select q;
char[] chs = p1.ToArray<char>();
strXml = new string(chs);
XDocument doc=XDocument.Parse(strXml);
var p = from q in doc.Element("Customers").Element("Customer").Elements() select q;
customer = new Customer
{
Unid = Convert.ToInt32(
p.Where(x => x.Name == "Unid").First<XElement>().Value),
CustomerName = (p.Where(x => x.Name == "CustomerName").
First<XElement>().Value).ToString(),
CreateTime = Convert.ToDateTime(p.
Where(x => x.Name == "CreateTime").
First<XElement>().Value),
Telephone = new Call {
Mobile = p.Where(y => y.Name == "Telephone").
First<XElement>().Elements().Where(x => x.Name == "Mobile").
First<XElement>().Value,
FirmCall = p.Where(y => y.Name == "Telephone").
First<XElement>().Elements().Where(x => x.Name == "FirmCall").
First<XElement>().Value,
HomeCall = p.Where(y => y.Name == "Telephone").
First<XElement>().Elements().Where(x => x.Name == "HomeCall").
First<XElement>().Value
}
};
ms.Close();
Console.WriteLine(customer.Unid);
}
}
服务端接收到xml后进行解析,分离数据。
服务端与客户端都以xml格式进行数据的解析和生成,xml就是他们共同的约定。