JAVA与.NET的相互调用——TCPIP相互调用基本架构(附原代).docx_第1页
JAVA与.NET的相互调用——TCPIP相互调用基本架构(附原代).docx_第2页
JAVA与.NET的相互调用——TCPIP相互调用基本架构(附原代).docx_第3页
JAVA与.NET的相互调用——TCPIP相互调用基本架构(附原代).docx_第4页
JAVA与.NET的相互调用——TCPIP相互调用基本架构(附原代).docx_第5页
已阅读5页,还剩19页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

TCP/IP套接字的概念 TCP/IP (传输控制协议/网际协议)是网络互连的通信协议,通过它可以实现各种异构网络或异种机之间的互联通信。TCP/IP是Transmission Control Protocol/Internet Protocol的简写,中文译名为传输控制协议/因特网 互联协议,又叫网络 通讯协议 ,这个协议是Internet最基本的协议、Internet国际 互联网 络 的基础,简单地说,就是由网络层的IP协议和传输层的TCP协议组成的。TCP/IP 定义了电子设备(比如计算机)如何连入因特网,以及数据如何在它们之间传输的标准。TCP/IP是一个四层的分层体系结构。高层为传输控制协议,它负责聚集信息或把文件拆分成更小的包。低层是网际协议,它处理每个包的地址部分,使这些包正确的到达目的地。 TCP/IP已成为当今计算机网络最成熟、应用最广的互联协议。Internet采用的就是 TCP/IP协议,网络上各种各样的计算机上只要安装了TCP/IP协议,它们之间就能相互通信。 TCP/IP套接字通讯的开发 在众多的开发语言中,绝大部分的开发语言都支持TCP/IP协议通讯,开发过程也十分相像,先设置好Socket,然后由客户端发送请求信息,服务器连接客户端接收到请求后再返还信息。而在.NET系统当中则稍有不同,系统把Socket对象包装在TcpClient对象内,对Socket对象的生命周期进行管理。在开发过程当中,服务器与客户端的开发语言有所不同的情况经常发生,服务器是在JDK1.6的环境下进行开发的,客户却要求使用.NET开发客户端,这往往会令开发人员感到困惑!下面在下使用JAVA为服务器,.NET为客户端为例子,为大家介绍一下如何使用TCP/IP协议进行JAVA .NET之间的相互调用。像TCP/IP实现聊天室这样的例子很多,开发起来也比较简单,因为通讯双方都是使用String来传送信息。而在真正建立 ERP、OA、CRM等系统的时候,通讯双方都必须先建立一套统一的通讯契约,才能实现TCP/IP通讯,下面将为大家介绍一个比较典型的企业信息通讯实例。 信息传送方式 因为.NET与JAVA各有不同的特性,双方不可能直接通过的序列化对象来传输信息,常用的信息交换方式有以下三种: 1. 最笨拙也是最复杂的一种传息方式,就是直接使用“头文件说明+字段属性”的方式。 这是一个既原始又麻烦的通讯方式,因为每个契约都要以二进制的方式发送一个请求,就算是同一类契约,随着参数的不同,每个请求的长度也会发生改变。这样的传息方式虽然是麻烦,但在不同开发语言相互调用的时候却经常会看到,这可能是因为开发人员对两种开发语言未能完全熟悉,所以倒置使用这最原始最简单的开发方式。 2. 使用XML的信息传送方式,这是最常见,使用最广的信息传递方式。在绝大多数的开发平台都会支持XML,所以XML在Web网络传讯过程中最为常见。但XML最大的一个缺点就是过于堪舆,耗费大量的传输流量。 3. 对于XML的缺点,JSON应运而生而且发展迅速,JSON本是源于Javascript的,多数只用于B/S的页面开发,但随着技术的发展和多个开发语言的支持,现今到处都可以看JSON的身影。因为JSON既提供一套跨平台的通讯方式,也免去XML复杂特性,受到各类型开发人员的欢迎。 服务器端开发 通讯契约首先建立一套服务器与客户端同时接受通讯契约, Contract 的name特性是契约的名称,服务器会通过此名称在Contracts.xml文件中找到该契约,然后根据output的package属性,class属性,method属性 找到该契约的包名称,类名,调用的方法等属性。 c-sharp:collapse + expand sourceview plaincopyprint?1. 2. /name为契约名,服务器与客户端必须同时遵守此契约 3. 4. 获取Age等于此值的People对象集/说明此契约内容 5. 6. 7. Manager/接收到GetPersonByAge请求时所调用的包名称 8. PersonManager/接收到GetPersonByAge请求时所调用的类名称 9. GetListByAge/接收到GetPersonByAge请求时所调用的处理方法名称 10. 11. 12. 13. 14. 获取ID等于此值的People对象15. 16. 17. Manager18. PersonManager19. GetListByID20. 21. 22. 以JSON方式实现信息传送尽管目前在C/S的开发当中大部分还是使用序列化对象和分节字段的方式进行双方通讯,但在这个实例当中,在下想以JSON通讯方式为例子来实现。首先,客户端会使用额定格式的JSON向服务器发送请求: “ContractName”:“GetPeopleByAge”,“Params”:23 ContractName代表着契约名称,系统会根据此名称 在Contracts.xml文件中 找到Name等于GetPeopleByAge的Contract项。然后在对应Output的子项Package,Class,Method中查找到对应的包,类型和方法。 Params是客户端传输过来的参数,服务器端会调用对象的方法输入参数23后,得到计算结果,最后把结果返还到客户端。 在这里有两点是值得注意的,第一点是JSON中的契约格式是固定的,服务器与客户端都必须遵守此契约,在ContractName中输入是必须对应的契约名称,而在Params中输入的必输是一个参数的集合,哪怕里面只包含有一个参数。第二点是在Contracts.xml文件,Output里面的 Package,Class,Method是服务器端自定义的,它只是绑定了服务器端实现GetPersonByAge契约的方法,而这些方法并不是固定,服务器可以根据系统的需要而修改。这个做法有点像Struts里面的Struts.xml文件,其意义就是要 使服务器的处理方法与客户端发送的请求实现分离。 基本结构 系统的基本结构如图,客户端会以JSON方式“ContractName”:“GetPeopleByAge”,“Params”:23 发送请求到服务器,服务器会利用“数据转换层”把接收到的请求转换成Contract对象。然后逻辑转换层会根据该Contract对象调用对应的方法,最后把计算结果以JSON方式返回到客户端。 注意在服务器与客户端信息交换的过程中,都是使用JSON格式 JSON数据转换 在服务器端,当接到到客户端请求后,Transfer类负责把接收到的JSON数据转换成Contract对象。在Transfer里面 使用org.json工具包作为JSON的转化工具,org.json工具包可于以下网址下载/java/index.html 。 而Implement类包含GetResult(Contract contract )方法,其作就是根据contract对象Package,Class,Method等属性,调用“逻辑转换层”的对应方法,最后把计算结果返还给InputControl。 服务器端接收请求后就会直接调用InputControl对输入的数据进行处理。 java:nogutter:collapse + expand sourceview plaincopyprint?1. /Contract实体类,包含契约的package,class,method,params等多个属性 2. packageModel;3. importorg.json.JSONArray;4. publicclassContract5. privateStringpackage1;6. privateStringclass1;7. privateStringmethod;8. privateJSONArrayparams;9. publicvoidsetPackage1(Stringpackage1)10. this.package1=package1;11. 12. publicStringgetPackage1()13. returnpackage1;14. 15. publicvoidsetClass1(Stringclass1)16. this.class1=class1;17. 18. publicStringgetClass1()19. returnclass1;20. 21. publicvoidsetMethod(Stringmethod)22. this.method=method;23. 24. publicStringgetMethod()25. returnmethod;26. 27. publicvoidsetParams(JSONArrayparams)28. this.params=params;29. 30. publicJSONArraygetParams()31. returnparams;32. 33. 34. /把输入的String字符串转化为Contract对象 35. /在这里使用org.json工具包作为JSON的转化工具,org.json工具包可于以下网址下载/java/index.html 36. packageCommon;37. importjava.io.File;38. importjava.io.IOException;39. importjavax.xml.parsers.DocumentBuilder;40. importjavax.xml.parsers.DocumentBuilderFactory;41. importjavax.xml.parsers.ParserConfigurationException;42. importModel.Contract;43. importorg.json.*;44. importorg.w3c.dom.Document;45. importorg.w3c.dom.Element;46. importorg.w3c.dom.NodeList;47. importorg.xml.sax.SAXException;48. publicclassTransfer49. privateTransfer()50. privatestaticStringcontractName=null;51. privatestaticContractcontract=newContract();52. privatestaticJSONObjectjsonObject=null;53. publicstaticContractGetContract(Stringdata)throwsException,JSONException,ParserConfigurationException,SAXException,IOException54. jsonObject=newJSONObject(data);/把字符串转化为JSONOject对象 55. GetContractName();/获取契约名称 56. GetProperty();/获取契约的package,class,method属性 57. GetParams();/获取契约的参数集 58. returncontract;59. 60. /*61. *获取契约对应的包名称,类名称,方法名称62. */63. privatestaticvoidGetProperty()throwsException64. Filefile=newFile(Contracts.xml);65. DocumentBuilderFactoryfactory=DocumentBuilderFactory.newInstance();66. DocumentBuilderbuilder=factory.newDocumentBuilder();67. Documentdoc=builder.parse(file);68. NodeListnodeList=doc.getElementsByTagName(Contract);69. ElementcontractElement=null;70. for(inti=0;inodeList.getLength();i+)71. if(nodeList.item(i).getAttributes().item(0).getNodeValue().equals(contractName)72. contractElement=(Element)nodeList.item(i);73. break;74. 75. 76. if(contractElement!=null)77. ElementoutputElement=(Element)contractElement.getElementsByTagName(Output).item(0);78. contract.setPackage1(outputElement.getElementsByTagName(Package).item(0).getTextContent();79. /获取包名称 80. contract.setClass1(outputElement.getElementsByTagName(Class).item(0).getTextContent();81. /获取类名称 82. contract.setMethod(outputElement.getElementsByTagName(Method).item(0).getTextContent();83. /获取方法名 84. 85. else86. thrownewException(未能找到对象的契约);87. 88. /*89. *获取契约名称90. */91. privatestaticvoidGetContractName()throwsJSONException92. contractName=jsonObject.getString(ContractName);93. 94. /*95. *获取输入参数96. */97. privatestaticvoidGetParams()throwsJSONException98. contract.setParams(jsonObject.getJSONArray(Params);99. 100. 101. /调用Contract对象里面包中的类的某个方法,获取计算结果 102. packageCommon;103. importjava.lang.reflect.Method;104. importjava.util.HashMap;105. importjava.util.Map;106. importorg.json.JSONArray;107. importModel.*;108. publicclassImplement109. privateContractcontract;110. privateStringfullName;111. privatestaticMapobjects=newHashMap();/保存对象实体 112. privatestaticMapclasses=newHashMap();/保存类名 113. /*114. *先获取对应的对象,再用反射模式调用对象的方法,获取计算结果115. */116. publicObjectGetResult(Contractcontract)117. this.contract=contract;118. this.fullName=contract.getPackage1()+.+contract.getClass1();119. try120. Objectmanager=GetObject();121. ClasstheClass=classes.get(fullName);122. Methodmethod=theClass.getDeclaredMethod(contract.getMethod(),JSONArray.class);123. returnmethod.invoke(manager,contract.getParams();124. catch(Exceptione)125. /TODOAuto-generatedcatchblock 126. e.printStackTrace();127. returnnull;128. 129. 130. /*131. *多次使用反射创建获取对象会损耗一定性能,所以此处使用单体模式获取对应的对象132. */133. privateObjectGetObject()throwsInstantiationException,IllegalAccessException,ClassNotFoundException134. if(!objects.containsKey(fullName)135. ClasstheClass=Class.forName(fullName);136. classes.put(fullName,theClass);137. Objectmanager=theClass.newInstance();138. objects.put(fullName,manager);139. 140. returnobjects.get(fullName);141. 142. 143. /直接把接收到的二进制数据转换成String,然后通过Transfer把String转化为Contract对象,最后通过Implement获取运算结果 144. packageCommon;145. importjava.io.DataInputStream;146. importModel.Contract;147. publicclassInputControl148. privateDataInputStreaminputStream;149. publicInputControl(DataInputStreaminputStream)150. this.inputStream=inputStream;151. 152. /*153. *直接把接收到的二进制数据转换成String,然后通过Transfer把String转化为Contract对象,最后通过Implement对象获取运算结果154. */155. publicObjectGetResult()156. bytebyteMessage=newbyte1024;/在此处只获取测试数据,在真正运行时应使用分批缓存的方式 157. try158. intn=inputStream.read(byteMessage);159. Stringmessage=newString(byteMessage,ASCII);160. Contractcontract=Transfer.GetContract(message);161. Implementimplement=newImplement();162. Objectresult=implement.GetResult(contract);163. returnresult;164. 165. catch(Exceptionex)166. ex.printStackTrace();167. returnnull;168. 169. 170. 最后,系统通过OutputControl类把计算结果返还给客户端。java:nogutter:collapse + expand sourceview plaincopyprint?1. /把计算结果返回到客户端 2. packageCommon;3. importjava.io.DataOutputStream;4. publicclassOutputControl5. privateDataOutputStreamoutputStream;6. publicOutputControl(DataOutputStreamoutputStream)7. this.outputStream=outputStream;8. 9. publicvoidOutput(Objectdata)10. try11. outputStream.writeBytes(data.toString();12. outputStream.flush();13. catch(Exceptionex)14. ex.printStackTrace();15. 16. 17. 18. /运行系统进行测试 19. packageCommon;20. importjava.io.*;21. .*;22. publicclassProgram23. privatestaticServerSocketserverSocket;24. publicstaticvoidmain(Stringargs)throwsClassNotFoundException25. /TODOAuto-generatedmethodstub 26. Socketsocket;27. try28. serverSocket=newServerSocket(5100);/激活5100端口 29. while(true)/循环捕捉请求 30. socket=serverSocket.accept();31. DataOutputStreamoutStream=newDataOutputStream(socket.getOutputStream();/获取DataOutputStream输出流 32. DataInputStreaminputStream=newDataInputStream(socket.getInputStream();/获取DataInputStream输入流 33. /调用InputControl对象获取运算结果 34. InputControlinputControl=newInputControl(inputStream);35. Objectresult=inputControl.GetResult();36. /调用OutputControl对象输入运算结果 37. OutputControloutputControl=newOutputControl(outStream);38. outputControl.Output(result);39. 40. catch(Exceptione)41. /TODOAuto-generatedcatchblock 42. e.printStackTrace();43. 44. 45. 逻辑转换层 现在先开发一个例子作为参考,在完成客户端开发的时候就可以进行测试。这个例子是先在Manager包里面设置好一个类 PersonManager,PersonManager类中包含一个名为GetListByAge的方法。在Contracts.xml文件设置一个名为GetPersonByAge的契约,客户端就可以通过这个契约在远程调用此方法获取计算结果。java:nogutter:collapse + expand sourceview plaincopyprint?1. /设置Person对象 2. packageModel;3. publicclassPerson4. privateintid;5. privateStringname;6. privateintage;7. publicvoidsetId(intid)8. this.id=id;9. 10. publicintgetId()11. returnid;12. 13. publicvoidsetName(Stringname)14. =name;15. 16. publicStringgetName()17. returnname;18. 19. publicvoidsetAge(intage)20. this.age=age;21. 22. publicintgetAge()23. returnage;24. 25. 26. /开发PersonManager 27. packageManager;28. importjava.util.ArrayList;29. importjava.util.List;30. importorg.json.JSONArray;31. importorg.json.JSONException;32. importModel.*;33. publicclassPersonManager34. /*35. *测试数据36. */37. privateListGetList()38. ListpersonList=newArrayList();39. Personperson1=newPerson();40. person1.setId(0);41. person1.setAge(23);42. person1.setName(Mike);43. personList.add(person1);44. Personperson2=newPerson();45. person2.setId(1);46. person2.setAge(29);47. person2.setName(Leslie);48. personList.add(person2);49. Personperson3=newPerson();50. person3.setId(2);51. person3.setAge(21);52. person3.setName(Jack);53. personList.add(person3);54. Personperson4=newPerson();55. person4.setId(3);56. person4.setAge(23);57. person4.setName(Rose);58. personList.add(person4);59. returnpersonList;60. 61. /*62. *获取年龄等于age参数的Person,因为数据将返还给客户端,所以这时把输出数据转化为JSONArray63. */64. publicJSONArrayGetListByAge(JSONArrayjsonList)throwsJSONException65. intage=jsonList.getInt(0);/因为输入参数为一个集合params,所以即使只包括一个参数,也是通过要jsonList的第一个参数来获取的。 66. ListpersonList=GetList();67. ListresultList=newArrayList();68. for(intn=0;npersonList.size();n+)69. if(personList.get(n).getAge()=age)70. resultList.add(personList.get(n);71. 72. JSONArrayjsonArray=newJSONArray(resultList);73. returnjsonArray;74. 75. 然后在Contracts.xml设置绑定java:nogutter:collapse + expand sourceview plaincopyprint?1. 2. /契约名称 3. 4. 获取Age等于此值的People对象集/文字说明 5. 6. 7. Manager/绑定包 8. PersonManager/绑定类 9. GetListByAge/绑定处理方法 10. 11. 12. 绑定以后,在完成客户端开发的时候就可以进行测试。使用这开发模式的好处在于利用JSON作用数据传输的桥梁,解决不同开发平台之间数据难以同步的问题。使用JSON比XML更容易操作,可以减少传输流量,而且受到各开发语言的支持。使用Contracts.xml在服务器绑定处理方式,使服务器的处理方法与客户端发送的请求实现分离。下面开始介绍一下客户端的开发。客户端开发 客户端的开发的开发相对简单,因为契约是使用 “ContractName”:“GetPeopleByAge”,“Params”:23 JSON方式进行传送,所以先开发一个MessageEntity实体类来承载契约。 c-sharp:nogutter:collapse + expand sourceview plaincopyprint?1. namespaceModel2. 3. DataContract4. publicclassMessageEntity5. 6. /契约名称 7. DataMember8. publicstringContractName9. 10. get;11. set;12. 13. /注意参数使用集合的方式来传送 14. DataMember15. publicIListParams16. 17. get;18. set;19. 20. 21. 然后开发一个MessageManager信息管理器来管理契约的传送过程,因为Framework4.0里面,未能对JSON数据中集合的转换提供一个简单函数,所以在MessageManager里面使用了一个 Newtonsoft.Json工具包,该工具包里面对JSON的操作有着强大支持,可以在/官方网站下载c-sharp:nogutter:collapse + expand sourceview plaincopyprint?1. usingSystem;2. usingSystem.Collections.Generic;3. usingSystem.Linq;4. usingSystem.Text;5. usingSystem.Net.Sockets;6. usingSystem.Runtime.Serialization.Json;7. usingSystem.IO;8. usingSystem.Threading;9. usingModel;10. usingNewtonsoft.Json;11. namespaceCommon12. 13. publicclassMessageManager14. 15. privatestaticTcpClient_tcpClient;16. /设置tcpClient对象 17. publicstaticTcpClientTcpClient18. 19. set_tcpClient=value;20. 21. /此处只使用静态方法实现数据传送,发送请求后使用Thread.Sleep等待运算结果,这样存在一定风险,也会降低效率 22. /在大型的开发当中应该进一步改善,把信息发送与信息接收分开处理 23. publicstaticobjectGetMessage(MessageEntitymessage,Typetype)24. 25. NetworkStreamnetworkStream=_tcpClient.GetStream();26. /利用DataContractJsonSerializer将MessageEntity对象实现序列化,发送到服务器 27. DataContractJsonSerializerjsonSerializer=newDataContractJsonSerializer(typeof(MessageEntity);28. lock(networkStream)29. 30. jsonSerializer.WriteObject(networkStream,message);31. networkStream.Flush();32. 33. Thread.Sleep(500);34. /获取回传信息,这里设置接收值1024个字节 35. /在实际的开发当中应该使用分批缓存的方式实现数据接收 36. bytemessageByte=newbyte1024;37. intn=0;38. lock(networkStream)39. n=networkStream.Read(messageByte,0,1024);40. if(n=0)41. returnnull;42. /根据输入的type对象,把二进制信息转化为对应的对象 43. stringjsonMessage=Encoding.ASCII.GetString(messageByte);44. /利用Netonsoft.Json工具集将获取的JSON数据转化对象 45. objectreturnValue=JavaScriptConvert.DeserializeObject(jsonMessage,type);46. returnreturnValue;47. 48. 49. 下面开发一个GetPersonByAge 契约作为例子 c-sharp:nogutter:collapse + expand sourceview plaincopyprint?1. Person实体例2. namespaceModel3. 4. publicclassPerson5. 6. privateint_id;7. privatestring_name;8. privateint_age;9. 10. publicintid11. 12. getreturn_id;13. set_id=value;14. 15. 16. publicintage17. 18. getreturn_age;19. set_age=value;20. 21. 22. publicstringname23. 24. getreturn_name;25. set_name=value;26. 27. 28. 29. /建立PersonDAL 30. usingSystem;31. usingSystem.Collections.Generic;32. usingSystem.Text;33. usingModel;34. usingCommon;35. namespaceDAL36. 37. publicclassPersonDA

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论