javaSocket通信原理
第一步:服务端创建serverSocket,启动服务、监听端口
/**
* 天气查询服务端
* @author SMN
* @version V1.0
*/
public class WeatherServer {
public static void main(String[] args) throws IOException {
//创建socket服务端对象
ServerSocket serverSocket = new ServerSocket(1234);
System.out.println("服务端已启动。。。。");
while(true){
//监听客户端连接,accept方法为阻塞方法
Socket socket = serverSocket.accept();
//获取输入流准备取客户端发送的数据
DataInputStream dataInputStream =null;
DataOutputStream dataOutputStream =null;
try {
//包括为datainputstream
dataInputStream = new DataInputStream(socket.getInputStream());
//读取数据
String in_data = dataInputStream.readUTF();
//打印读取的数据
System.out.println("from client.."+in_data);
//创建输出流准备输出数据
dataOutputStream = new DataOutputStream(socket.getOutputStream());
System.out.println("to client..."+"晴朗");
dataOutputStream.writeUTF("晴朗");
} catch (Exception e) {
e.printStackTrace();
}finally{
//释放资源
if(dataOutputStream!=null){
dataOutputStream.close();
}
if(dataInputStream!=null){
dataInputStream.close();
}
}
}
}
}
第二步:客户端创建socket,连接服务端
/**
* 天气查询客户端
* @author SMN
* @version V1.0
*/
public class WeatherClient {
public static void main(String[] args) throws UnknownHostException, IOException {
while(true){
//socket客户端对象
Socket socket = null;
//输出流用于发送数据
DataOutputStream dataOutputStream = null;
//输入流用于接收数据
DataInputStream dataInputStream = null;
try {
//创建socket
socket = new Socket("127.0.0.1", 1234);
socket.setSoTimeout(10000);//超时时间为10秒,防止服务端处理超时返回数据失败
//创建输出流准备向服务端发送数据
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataOutputStream.writeUTF("郑州");
System.out.println("to server...."+"郑州");
//接收服务端发送的数据
dataInputStream = new DataInputStream(socket.getInputStream());
String resultString = dataInputStream.readUTF();
System.out.println("from server..."+resultString);
} catch (Exception e) {
e.printStackTrace();
}finally{
//释放资源
if(socket!=null){
socket.close();
}
if(dataOutputStream!=null){
dataOutputStream.close();
}
if(dataInputStream!=null){
dataInputStream.close();
}
}
}
}
}
第一步:服务端开发
1.编写SEI(Service Endpoint Interface),SEI在webservice中称为portType,在java中称为接口。
/**
* 天气查询服务接口
* @author SMN
* @version V1.0
*/
public interface WeatherInterface {
//天气查询
public String queryWeather(String cityName);
}
2.编写SEI实现类,此类作为webservice提供服务类
/**
* 天气查询服务接口实现类
* @author SMN
* @version V1.0
*/
@WebService
public class WeatherInterfaceImpl implements WeatherInterface {
@Override
public String queryWeather(String cityName) {
System.out.println("from client.."+cityName);
String result = "晴朗";
System.out.println("to client..."+result);
return result;
}
public static void main(String[] args) {
//发送webservice服务
Endpoint.publish("http://192.168.1.100:1234/weather", new WeatherInterfaceImpl());
}
}
注意:
SEI实现类中至少要有一个非静态的公开方法需要作为webservice服务方法。
public class 上边要加上@WebService
3.endpoint发布服务,代码在实现类的主方法中
第二步:查看wsdl
Webservice发布成功,通过wsdl查看webservice发布的正确性
1.在地址栏输入(注意后面的参数?wsdl)
http://192.168.1.100:1234/weather?wsdl
2.Wsdl不是webService,只是获取一个用于描述WebService的说明文件
3.wsdl- WebServiceDescriptionLanguage,是以XML文件形式来描述WebService的”说明书”,有了说明书,我们才可以知道如何使用或是调用这个服务.
第三步:Wsimport生成客户端调用类
Wsimport介绍
wsimport是jdk自带的webservice客户端工具,可以根据wsdl文档生成客户端调用代码(java代码).当然,无论服务器端的WebService是用什么语言写的,都可以生成调用webservice的客户端代码,服务端通过客户端代码调用webservice。
wsimport.exe位于JAVA_HOME\bin目录下.
常用参数为:
-d<目录> - 将生成.class文件。默认参数。
-s<目录> - 将生成.java文件。
-p<生成的新包名> -将生成的类,放于指定的包下。
(wsdlurl) - http://server:port/service?wsdl,必须的参数。
示例:
C:/> wsimport –s . http://127.0.0.1:1234/weather?wsdl
注意:-s不能分开,-s后面有个小点
输入以下命令:
参数说明:-s是指编译出源代码文件,后面的.(点)指將代码放到当前目录下.
最后面的http….是指获取wsdl说明书的地址.
如果wsdl文件在本地,可以这样使用:Wsimport –s . file:///d:\WeatherWebService.wsdl
注意:这里可能会遇到类似这样的错误:
我们可以把wsdl文件下载到本地,删除掉文件中所有的<s:element ref="s:schema"/>即可解决
4.生成完成,刷新Eclipse中wsimport工程,将src下生成.java文件代码Copy到webservice客户端工程(见下)中。
第四步:客户端编写
/**
* 天气查询客户端
* @author SMN
* @version V1.0
*/
public class WeatherClient {
public static void main(String[] args) {
//创建服务视图
WeatherInterfaceImplService weatherInterfaceImplService =new WeatherInterfaceImplService();
//通过服务视图得到服务端点
WeatherInterfaceImpl weatherInterfaceImpl= weatherInterfaceImplService.getPort(WeatherInterfaceImpl.class);
//调用webservice服务方法
String result = weatherInterfaceImpl.queryWeather("郑州");
System.out.println(result);
}
}
Socket 是基于TCP/ip的传输层协议
Webservice是基于http协议传输数据,http是基于tcp的应用层协议
Webservice采用了基于http的soap协议传输数据。
Socket接口通过流传输,不支持面向对象。
Webservice 接口支持面向对象,最终webservice将对象进行序列化后通过流传输。
结论:
Webservice采用soap协议进行通信,底层基于socket通信,webservice不需专门针对数据流的发送和接收进行处理,是一种跨平台的面向对象远程调用技术。
Socket和webservice:应用场景
Socket适用于传输大数量的数据,缺点:接口传输的数据需要手动解析,socket通信的接口协议需要自定义,比如:自定义一种字符串拼接的格式,比如自定义的xml数据,自定义麻烦之处在接口调用方和接口服务端需要互相讨论确定接口的协议内容,不方便,好处:适用于传输大数量的数据。
Webservcie,由于是遵循标准的soap协议,soap 协议的内容格式固定,soap协议传递的内容是xml数据,由于webservice是基于http的,所以简单理解为soap=http+xml,适用于没有性能要求情况下且数据传输量小,推荐在公开接口上使用webservice,因为soap协议的标准的。
Web service 即web服务,它是一种跨编程语言和跨操作系统平台的远程调用技术即跨平台远程调用技术。
采用标准SOAP(Simple Object Access Protocol) 协议传输,soap属于w3c标准。Soap协议是基于http的应用层协议,soap协议传输是xml数据。
采用wsdl作为描述语言即webservice使用说明书,wsdl属w3c标准。
xml是webservice的跨平台的基础,XML主要的优点在于它既与平台无关,又与厂商无关。
XSD,W3C为webservice制定了一套传输数据类型,使用xml进行描述,即XSD(XML Schema Datatypes),任何编程语言写的webservice接口在发送数据时都要转换成webservice标准的XSD发送。
SOAP即简单对象访问协议(Simple Object Access Protocal) 是一种简单的基于 XML 的协议,它使应用程序通过 HTTP 来交换信息,简单理解为soap=http+xml。
Soap协议版本主要使用soap1.1、soap1.2
SOAP不是webservice的专有协议,其他应用协议也使用soap传输数据。例如,SMTP、tr069等。
WSDL 是基于 XML 的用于描述Web Service及其函数、参数和返回值。通俗理解Wsdl是webservice的使用说明书。
UDDI 是一种目录服务,通过它,企业可注册并搜索 Web services。企业将自己提供的Web Service注册在UDDI,也可以使用别的企业在UDDI注册的web service服务,从而达到资源共享。
UDDI旨在将全球的webservcie资源进行共享,促进全球经济合作。
但是使用webservice并不是必须使用UDDI,因为用户通过WSDL知道了web service的地址,可以直接通过WSDL调用webservice。
wsdl 说明书结构
<service> 整个webservice的服务视图,它包括了所有的服务端点
<binding> 为每个端口定义消息格式和协议细节
<portType> 描述 web service可被执行的操作,以及相关的消息,通过binding指向portType
<message> 定义一个操作(方法)的数据参数(可有多个参数)
<types> 定义 web service 使用的全部数据类型
wsdl 说明书阅读方式
从下往上读
先找到服务视图,通过binging找到protType,找到了protType就找到了我们要调用的webservice方法。
查看wsdl说明要从下往上看:
1服务视图(根)
2通过服务视图,bingding到porttype
3、调用portType的方法
第一步:创建URL,指定资源地址即wsdl地址
第二步:创建Qname,指定命名空间和视图名称
第三步:创建服务视图对象service
第四步:从服务视图中得到服务端点即服务接口(这里需要服务接口类型,可使用wsimport生成后只留下porttype)
第五步:通过服务端点调用服务方法
/**
* 使用javax.xml.ws.Service调用webservice服务
* @author SMN
* @version V1.0
*/
public class WeatherClient2 {
public static void main(String[] args) throws MalformedURLException {
//定义url,参数为wsdl地址
URL url = new URL("http://192.168.1.100:1234/weather?wsdl");
//定义qname,第一个参数是命名空间,第二个参数名称是wsdl里边的服务名
QName qName = new QName("http://impl.sei.jaxws.ws.itcast.cn/", "WeatherInterfaceImplService");
//创建服务视图
Service service = Service.create(url, qName);
//通过服务视图得到服务端点
WeatherInterfaceImpl weatherInterfaceImpl =service.getPort(WeatherInterfaceImpl.class);
//调用webservice
System.out.println(weatherInterfaceImpl.queryWeather("郑州"));
}
}
Wsimport生成代码调用webservice无法指定webservice的地址,使用生成的服务视图类获取服务端点(postType)实例。
Service调用Webservice可以指定webservice的地址,只需要服务端点的接口即可获取服务端点实例。