不同客户端与java服务器端实现通信的论述.docx

上传人:b****7 文档编号:11361283 上传时间:2023-02-28 格式:DOCX 页数:17 大小:57.07KB
下载 相关 举报
不同客户端与java服务器端实现通信的论述.docx_第1页
第1页 / 共17页
不同客户端与java服务器端实现通信的论述.docx_第2页
第2页 / 共17页
不同客户端与java服务器端实现通信的论述.docx_第3页
第3页 / 共17页
不同客户端与java服务器端实现通信的论述.docx_第4页
第4页 / 共17页
不同客户端与java服务器端实现通信的论述.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

不同客户端与java服务器端实现通信的论述.docx

《不同客户端与java服务器端实现通信的论述.docx》由会员分享,可在线阅读,更多相关《不同客户端与java服务器端实现通信的论述.docx(17页珍藏版)》请在冰豆网上搜索。

不同客户端与java服务器端实现通信的论述.docx

不同客户端与java服务器端实现通信的论述

不同客户端与java服务器端实现应用的论述

一.flex+java关键技术

1.1Flex的介绍

FLEX的开发环境就是FlexBuilder,利用FlexBuilder,开发者可以通过拖拽方式开发人机界面。

FLEX是排版打印软件和图形渲染软件巨头Adobe公司在其著名的FLASH平台(FlashPlayer)上,用ActionScript语言开发的一套RIA软件开发套件(SDK)及其集成开发环境。

FLEXSDK由Flex框架类库,FLEX编译器,调试器,MXML和ActionScript编程语言以及其他工具组成。

1.2MXML和ActionScript简介

在基于HTML的网页开发中,我们用HTML标记语言进行布局,用javascript语言操作HTML组件。

FLEX中也混合使用两种类似的语言来进行应用开发,它们是MXML和ActionScript。

与HTML类似,MXML是一种XML标记语言,使用它能方便快捷地完成人机界面组件的布局。

与javascript类似,ActionScript是一种脚本语言,用来操作MXML组件。

MXML与HTML的不同的是:

MXML拥有更丰富,表现力更强的标记集合。

MXML还包括了一些人机交互无关的不可忽视组件的标记。

可以扩展已有的MXML标记形成新的自定义MXML标记,而应用中的MXML代码最终会被编译到SWF文件中,然后在FlashPlayer中运行。

1.3BlazeDS介绍

FLEX应用程序运行在客户端环境中,若干个这样的应用程序连同服务器共同组成了一个完整的应用。

这些程序需要服务器提供数据或其他服务,BlazeDS为这种通信方式提供了稳定,高效的支持。

BlazeDS的消息服务支持建立在HTTP协议之上的消息发布及订阅。

AdobeFlex或者

AJAX客户端通过订阅一个或多个主题以接受服务器推送来的数据。

使用此服务,开发者能够创建实时协作或者数据推送应用程序。

BlazeDS在应用系统中所处的地位如:

图1所示

2.系统运行环境

客户端:

操作系统:

Windows98/NT/2000/XP或更高版本

浏览器:

IE5.0以上或Netscape同等版本以上

服务器:

操作系统:

Windows2000Server或者Windows2003Server

Web服务器:

MSIIS

应用服务器:

tomcat、COM+等企业级应用服务器

数据库:

SQLServer2000

 

3.系统设计

Flex相比传统的OA是显示界面的全新体验。

3.1从分层角度来看,企业应用分为三个层次。

如表1所示

展现层主要负责信息展示以及用户与软件之间的交互逻辑“,展现层”接受用户输入并将用户的意图转换为对“领域层”或“数据源层”逻辑的调用。

领域层也被称为“业务逻辑层”,主要解决应用针对业务领域的问题,该层负责校验来自“展现层”的输入数据,根据“展现层”用户指令进行业务逻辑处理,调用“数据源层”的逻辑实现数据的访问和持久化。

数据源层主要负责数据访问和持久化,数据可能来自于数据库或者其他文件。

Flex+JAVA开发的应用中“,展现层”逻辑完全运行在客户端的FLASH虚拟机中,而“领域层”和“数据源层”逻辑则运行在服务器端的java虚拟机中,如图2所示

3.2确定通信框架

开发异构系统的时候,如何进行通信和传递数据,使用FLEX+JAVA开发基于C/S结构企业应用,客户端和服务器端的通信协议是HTTP协议。

在FLEX中,基于HTTP协议访问服务器的通信组件有三个:

HttpService

WebService

RemoteObject

在企业应用开发中大部分都使用RemoteObject完成的,RemoteObject组件在BlazeDS的配合下能够调用后台服务器对象上的方法,从而实现客户端与服务器端的通信。

下面给出一段代码展示RemoteObject对象的使用:

PublicfuncionuserRemoteObject(intArg:

int,

strArg:

String):

void{

employeeRO=newRemoteObject();

employeeRO.destionation=“SalaryManager”;

employee.getList.addEventListener(“result”,getListResultHandler);

employeeRO.addEventListener(“fault”,faultHandler);

employeeRO.getList(deptComboBox,selectedItem,data);

}

上面代码中,首先使用语句:

employeeRO=newRemoteObject();创建了一个RemoteObject对象employeeRO。

然后通过语句:

employeeRO.destionation=“SalaryManager”将RemoteObject对象的destionation属性赋值为“SalaryManager”,destionation属性表示远程对象调用的“目的地”,请求发送到服务器端后,服务器端的“第三方软件”接收到请求后会检查配置文件,找到destionation值所映射的“服务器端组件”,从而可以调用该组件上的方法。

接下来使用语句:

employee.getList.addEventListener(“result”,getListResultHandler);设置远程服务调用成功时的处理方法,使用语句:

employeeRO.addEventListener(“fault”,faultHandler);设置远程服务调用失败时的处理方法。

最后使用语句:

employeeRO.getList(deptComboBox,selectedItem,data);

以deptComboBox,selectedItem,data为参数,调用destionation属性所映射的“服务器端组件”的getList方法。

这里“服务器组件”必须有一个名为getList的公开方法,调用“服务器端组件”的getList方法是异步调用的,因此它不会阻塞线程来等待调用结果的返回。

二.C#+java技术

1.c#的介绍

C#语言自C/C++演变而来。

它现代、简单、完全面向对象和类型安全。

关于C#最重要的一点:

它是现代的编程语言。

它简化和现代化了C++在类、名字空间、方法重载和异常处理等领域。

屏弃了C++的复杂性,使它更易用、更少出错。

2.运行环境

客户端:

操作系统:

Windows98/NT/2000/XP或更高版本

浏览器:

IE5.0以上或Netscape同等版本以上

服务器:

操作系统:

Windows2000Server或者Windows2003Server

Web服务器:

MSIIS

应用服务器:

tomcat、COM+等企业级应用服务器

数据库:

SQLServer2000

 

3.相关实现

C#客户端与JAVA服务器端的TCP文件传输使用两种计算机语言的结合。

可以用WebService做,也可用socket。

因为不管什么类型的计算机语言,都是用机器语言封装的,越是底层的技术,就越容易结合。

socket技术很底层,但效率确实最高,对于JAVA以及C#的初学者来说,又简单易懂。

首先是JAVA的服务器端,这个只要学习过J2SE网络编程的人,应该都能做得出来。

代码如下:

packagecom.ly.image;

importjava.io.BufferedInputStream;

importjava.io.BufferedWriter;

importjava.io.File;

importjava.io.FileOutputStream;

importjava.io.FileWriter;

importjava.io.ObjectInputStream;

importjava.io.PrintWriter;

import.ServerSocket;

import.Socket;

importjava.text.SimpleDateFormat;

importjava.util.Date;

importjava.util.Locale;

importjava.util.ResourceBundle;

importorg.apache.log4j.Logger;

/**

*TCP服务器端

*/

publicclassTCPServer{

privatestaticLoggerlogger=Logger.getLogger(TCPServer.class);

/**

*接收文件存放路径

*/

privatestaticStringpath;

/**

*接收端口

*/

privatestaticintport;

/**

*读取资源文件

*通过资源文件读取所需资源,方便更改,资源文件里有文件存放路径及接收端口

*/

static{

System.out.print("读取配置文件...");

//资源绑定

ResourceBundlerb=ResourceBundle.getBundle("config",Locale.getDefault());

path=rb.getString("path");

StringportStr=rb.getString("port");

if(path==null||path.trim().equals("")){

path="E:

/";

}elseif(!

path.endsWith("/")){

path=path+"/";

}

if(portStr!

=null||!

portStr.trim().equals("")){

try{

port=Integer.parseInt(portStr);

}catch(Exceptionex){

System.out.println("端口获取失败,已变更为默认端口8888");

port=8888;

}

}else{

System.out.println("未配置端口,已变更为默认端口8888");

port=8888;

}

System.out.println("读取完成:

"+"接收端口"+port+",接收路径"+path);

}

/**

*启动服务

*/

publicstaticvoidmain(String[]args){

newTCPServer().receiveFile();

}

/**

*接收文件

*/

publicvoidreceiveFile(){

ServerSocketss=null;

Sockets=null;

BufferedInputStreamin=null;

FileOutputStreamout=null;

try{

ss=newServerSocket(port);

System.out.println("服务已正常启动!

");

}catch(Exceptionex){

ex.printStackTrace();

System.out.println("服务启动失败!

");

logger.error("启动服务失败!

"+ex);

}

//永不停歇地运行

while(true){

byte[]buffer=newbyte[1024];

StringfileName=null;

try{

s=ss.accept();

in=newBufferedInputStream(s.getInputStream());

//取得文件名

in.read(buffer,0,buffer.length);

fileName=newString(buffer).trim();

//若为测试信息

if(fileName.equals("testmessage")){

System.out.println("接收到测试消息!

");

logger.info("接收到测试消息!

");

continue;

}

//定义文件流

out=newFileOutputStream(newFile(path+fileName));

out.flush();

buffer=newbyte[1024];

//写文件内容

intcount=0;

while((count=in.read(buffer,0,buffer.length))>0){

out.write(buffer,0,count);

out.flush();

buffer=newbyte[1024];

}

System.out.println("接收到文件"+fileName);

logger.info("接收到文件"+fileName);

}catch(Exceptionex){

System.out.println("传输异常");

logger.error("传输异常",ex);

ex.printStackTrace();

}finally{

try{

if(out!

=null){

out.close();

}

if(in!

=null){

in.close();

}

if(s!

=null){

s.close();

}

}catch(Exceptionex){

ex.printStackTrace();

logger.error("接收文件"+fileName+"失败"+ex);

}

}

}

}

}

使用此服务器接收时,过程如下:

1.从流中读取第一拨数据,作为接收到文件的文件名(若接收到的为定义好的测试信息,则跳过本次循环)

2.用上一步得到的文件名定义文件流

3.从流中以1K为单位,读取字节内容,并写入文件流

然后是C#的客户端代码:

usingSystem;

usingSystem.Collections.Generic;

usingSystem.Configuration;

usingSystem.IO;

usingSystem.Net;

usingSystem.Net.Sockets;

usingSystem.Text;

namespaceClient

{

classProgram

{

///

///发送文件

///

///文件全路径

///文件名

///返回执行结果0成功,-1文件不存在,-2连接失败,-3IO异常,-4未知异常

publicintStartSend(Stringpath,StringfileName)

{

if(!

File.Exists(path))

{

return-1;

}

NetworkStreamstream=null;

BinaryWritersw=null;

FileStreamfsMyfile=null;

BinaryReaderbrMyfile=null;

try

{

TcpClientclient=newTcpClient("172.16.60.30",8888);

stream=client.GetStream();

sw=newBinaryWriter(stream);

///取得文件名字节数组

byte[]fileNameBytes=Encoding.Default.GetBytes(fileName);

byte[]fileNameBytesArray=newbyte[1024];

Array.Copy(fileNameBytes,fileNameBytesArray,fileNameBytes.Length);

///写入流

sw.Write(fileNameBytesArray,0,fileNameBytesArray.Length);

sw.Flush();

///获取文件内容字节数组

///byte[]fileBytes=returnbyte(filePath);

fsMyfile=newFileStream(path,FileMode.OpenOrCreate,FileAccess.ReadWrite);

brMyfile=newBinaryReader(fsMyfile);

///写入流

byte[]buffer=newbyte[1024];

intcount=0;

while((count=brMyfile.Read(buffer,0,1024))>0)

{

sw.Write(buffer,0,count);

sw.Flush();

buffer=newbyte[1024];

}

}

catch(SocketExceptionse)

{

Console.WriteLine(se.StackTrace);

return-2;

}

catch(IOExceptionioe)

{

Console.WriteLine(ioe.StackTrace);

return-3;

}

catch(Exceptionex)

{

Console.WriteLine(ex.StackTrace);

return-4;

}

finally

{

if(sw!

=null)

{

sw.Close();

}

if(brMyfile!

=null)

{

brMyfile.Close();

}

if(fsMyfile!

=null)

{

fsMyfile.Close();

}

if(stream!

=null)

{

stream.Close();

}

}

return0;

}

///

///测试通讯

///

///成功失败

publicboolTestConnection()

{

NetworkStreamstream=null;

BinaryWritersw=null;

try

{

TcpClientclient=newTcpClient("172.16.60.30",8888);

stream=client.GetStream();

sw=newBinaryWriter(stream);

byte[]fileNameBytes=Encoding.Default.GetBytes("testmessage");

sw.Write(fileNameBytes,0,fileNameBytes.Length);

returntrue;

}

catch(Exceptionex)

{

returnfalse;

}

}

}

}

这个发送端有两个方法,其中第二个方法是测试连接用的,返回true即为测试通过,返回false连接异常。

发送过程如下:

1.先把文件名写入流,供服务器端读取

2.将文件内容写入流

3.若发送完毕,返回0;给定文件不存在,返回-1;连接异常,返回-2;IO异常返回-3;其他异常返回-4。

C#和JAVA虽然很相似,但是毕竟方向不同,各有各的长处,各有各的规范。

使用socket时,也遇到了不太匹配的地方。

比如开始用C#发送文件名的时候,我只把文件名转变为字节流,没有指定固定长度。

这样使用JAVA接收时,导致文件最后一部分字节残留,使得第二次接收文件时,文件名不能正确显示。

于是才在C#的发送端用Array.Copy方法,将文件名字节流补足了1K,才正常传输。

3.不同实现之间的对比

在某大型项目中,客户要求不能用浏览器作为客户端(即不能用B/S模式),而要采用桌面客户端的方式(服务端用SSH,客户端通过WebService访问服务端应用,并且还要求能在客户端与服务端网络中断的情况下离线进行部分业务操作,例如查询)。

这可给我们项目组提出了一个大问题:

客户端应用开发的技术选型。

1.flex做客户端

Flex是基于MXML与Actionscript3,在FlexBuilder3下开发,借助编译器可以在开发时发现编译异常,在运行时可以通过设置断点来分步调试,而MXML的底层实际上也是Actionscript3,这无论从开发、设计还是调试方面都比传统的HTML+Javascript要强大的多。

当客户端变得很慢、内存泄露、甚至溢出时,我们往往只是对客户一笑,告诉他重启浏览器。

由于不好的开发习惯,很多项目代码中充斥着垃圾回收机制无法回收的内存占用,这些内存浪费就是所谓的内存泄露,更可怕的是,当你的程序运行时间越长,会累积越来越多的内存泄露,最终导致内存溢出,系统崩溃。

Flex的profile可以轻松帮助我们发现内存溢出的根源,帮助我们写出功能性能俱佳的代码。

另外,利用Flex还有客户和服务器端部署方便,客户端与服务器完全独立,丰富的框架等优点

2.c#做客户端

在用C#做客户端得问题上,公司有些员工强烈建议用JavaSwing,认为有一些框架可以利用,例如SpringRichClient(Swing),大家都对Spring比较熟悉,有亲近感;甚至可以考虑使用EclipseRCP富客户端平台(SWT),因为有Eclipse在前面作为成功标杆。

并且公司开发人员绝大多是Java程序员,可以随时抽调精兵强将加入任务繁重的客户端开发中,解决技术难题,甚至突击编写普通业务功能。

而C#人员要重新招聘,增加了很多不确定因素。

但是采用Swing,缺点是界面比较难看,控件少得可怜,对客户端资源的控制能力差,开发难度肯定高,并且公司内部也没有积累(Java程序员都是做B/S应用的),并且在人力资源市场上,Swing方面但凡有点水平的开发人员工资都高得吓人(在51Job上查了一下);但好处就是应用服务端与客户端都是用的Java,两边的人手可以灵活配置(当然前题是开发人员对于SSH和Swing都要能上手,一是需要一段时间学习,二是人家技能多了,肯定会要

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1