`
pengjianf_ah
  • 浏览: 8592 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

java socket调用webservice以及如何解决连接重置报错问题

阅读更多
一、写这篇记录的原因:
最近看了一些关于关于socket模拟文件服务器的文章或者视频,客户端通过浏览器访问,服务端通过socket去实现,学习之下了解到就是向socket发送制定格式的内容【http协议】,然后服务端进行解析,返回相关的数据,于是就想肯定要可以使用socket模拟调用webservice【webservice就是http协议+soap报文通过tcp协议来传输】,当然了使用httpclient去模拟发送get/post请求最方便,不过也是自己对http协议深入理解【原来的理解就知道http协议是什么样的,但是具体发送的啥内容也模糊】

二、直接贴代码:
1.调用部分
package com.pjf.netbase;

import com.pjf.netentity.Response;
import com.pjf.netservice.ClientService;

public class WebServiceClient {
	public final static int BYTELEN = 1024;// 经测试64个字节以上没有问题

	public static void main(String[] args) throws Exception {

		// BufferedReader br=new BufferedReader(new InputStreamReader(new
		// FileInputStream("1.txt")));
		// String str="";
		// while((str=br.readLine())!=null){
		// System.out.println(str);
		//
		// }
		//
		long startTime = System.currentTimeMillis();
		System.out.println();
		// Socket socket = new Socket("www.webxml.com.cn", 80);
		// PrintWriter pw = new PrintWriter(socket.getOutputStream());
		String req = /*
						 * "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" +
						 */ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\r\n"
				+ "<soap:Body>\r\n" + "<getSupportCity xmlns=\"http://WebXml.com.cn/\">\r\n"
				+ "<byProvinceName>安徽</byProvinceName>\r\n" + "</getSupportCity>\r\n" + "</soap:Body>\r\n"
				+ "</soap:Envelope>\r\n";

		String head = "POST /WebServices/WeatherWebService.asmx HTTP/1.1\r\n" + "Host: www.webxml.com.cn\r\n"
				+ "Content-Type: text/xml; charset=utf-8\r\n" + "Content-Length:" + req.getBytes().length + "\r\n"
				+ "SOAPAction: \"http://WebXml.com.cn/getSupportCity\"\r\n\r\n";

		Response res = ClientService.callWebService(head, req, "www.webxml.com.cn", 80);
		if (res.getStatus().equals("999")) {
			System.out.println("连接异常,请检查连接");
		} else {
			System.out.println(res.toString());
		}

		// System.out.println(head + str);
		// pw.println(head + str);
		// pw.flush();

		// // 接受客户端的响应
		// byte[] b = new byte[BYTELEN];
		// byte[] context = null;
		// byte[] headbyte = null;
		// InputStream is = socket.getInputStream();
		// int len = 0;
		//
		// int start_position = 0;
		// int end_position = 0;
		// int contlen = 0;
		// boolean isContinue = true;
		// while ((len = is.read(b)) != -1) {
		// System.out.println("每次读取的长度:" + len);
		// // 解析内容
		// if (isContinue) {
		// // 针对头部信息,防止制定的字节一个byte[len]你不够,此处进行字节数组拼接
		// if (headbyte == null) {
		// headbyte = new byte[len];
		// System.arraycopy(b, 0, headbyte, 0, len);
		//
		// } else {
		// byte[] tmp = new byte[headbyte.length + len];
		// System.arraycopy(headbyte, 0, tmp, 0, headbyte.length);
		// System.arraycopy(b, 0, tmp, headbyte.length, len);
		// headbyte = tmp;
		// b = tmp;
		//
		// }
		//
		// for (int i = start_position; i < b.length; i++) {
		// if (b[i] == '\r') {
		// end_position = i;
		// String data = new String(b, start_position, end_position -
		// start_position);
		// if (data.contains("Content-Length")) {
		// // System.out.println("----contlen"+data);
		// contlen = Integer.parseInt(data.split(" ")[1]);
		// }
		//
		// System.out.println("每次读取输出的内容:" + data);
		// start_position = i + 2;
		// i = i + 1;
		// if (data.equals("")) {
		// isContinue = false;
		// System.out.println("内容准备读取,跳出循环准备全部去读");
		// break;
		// }
		//
		// }
		//
		// }
		// }
		// // 如果头结点已经读取完毕,则进行保留内存的内容结点
		// if (isContinue == false) {
		//
		// if (context == null) {
		// context = new byte[b.length - start_position];
		// if (b.length - start_position > 0) {
		// System.arraycopy(b, start_position, context, 0, b.length -
		// start_position);
		// }
		// // 需要判断是否立即结束 ----针对于一次读完的情况,加入此判断,否则可能存在问题
		// if (len < BYTELEN) {
		// break;
		// }
		// }
		// // } else if (len < BYTELEN) {//bug就出现在这
		// // byte[] tmp = new byte[context.length + len];
		// // System.arraycopy(context, 0, tmp, 0, context.length);
		// // System.arraycopy(b, 0, tmp, context.length, len);
		// // context = tmp;
		// // break;
		// // }
		// else {
		// byte[] tmp = new byte[context.length + len];
		// System.arraycopy(context, 0, tmp, 0, context.length);
		// System.arraycopy(b, 0, tmp, context.length, len);
		// context = tmp;
		// System.out.println((context.length) + "-------------" + contlen);
		// if (context.length == contlen) {// 表示数据读取完毕
		// break;
		// }
		// }
		//
		// }
		//
		// }
		// long endTime = System.currentTimeMillis();
		// System.out.println("使用时间:" + (endTime - startTime));
		// System.out.println(new String(context));
		// System.out.println("处理完毕");
		// pw.close();
		// socket.close();
	}

}



2.Response对象定义
package com.pjf.netentity;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 
 * @author pengjf 作为调用webservice的返回对象封装
 *
 */
public class Response {
	private String status;// 状态
	private String statusNum;
	private String version;

	public Response() {
		status = "-999";
	}

	public String getStatusNum() {
		return statusNum;
	}

	public void setStatusNum(String statusNum) {
		this.statusNum = statusNum;
	}

	public String getVersion() {
		return version;
	}

	public void setVersion(String version) {
		this.version = version;
	}

	private Map<String, String> headMap = new HashMap<String, String>();// 头节点
	private String resultSoapXml = "";// 解析内容

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public Map<String, String> getHeadMap() {
		return headMap;
	}

	public void setHeadMap(Map<String, String> headMap) {
		this.headMap = headMap;
	}

	public String getResultSoapXml() {
		return resultSoapXml;
	}

	public void setResultSoapXml(String resultSoapXml) {
		this.resultSoapXml = resultSoapXml;
	}

	@Override
	public String toString() {
		String result = "";
		Iterator iter = headMap.entrySet().iterator();
		while (iter.hasNext()) {
			Map.Entry entry = (Map.Entry) iter.next();
			result += entry.getKey() + "-->" + entry.getValue() + "\r\n";
		}

		return status + " " + statusNum + " " + version + "\r\n" + result + "\r\n" + resultSoapXml;
	}
}




3.核心处理部分[调用+解析]
package com.pjf.netservice;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

import com.pjf.netentity.Response;

public class ClientService {
	public static int BYTELEN = 1024;

	public static Response callWebService(String head, String request, String host, int port)
			throws UnknownHostException, IOException {

		Socket socket = new Socket(host, port);
		PrintWriter pw = new PrintWriter(socket.getOutputStream());
		pw.println(head + request);
		pw.flush();
		Response res = praseInputStrem(socket);
		pw.close();
		pw = null;
		return res;
	}

	public static Response praseInputStrem(Socket socket) {
		Response res = new Response();
		try {
			long startTime = System.currentTimeMillis();
			// 接受客户端的响应
			byte[] b = new byte[BYTELEN];
			byte[] context = null;
			byte[] headbyte = null;
			InputStream is = socket.getInputStream();
			int len = 0;

			int start_position = 0;
			int end_position = 0;
			int contlen = 0;
			boolean isContinue = true;
			boolean isFirstLine = true;
			while ((len = is.read(b)) != -1) {
				System.out.println("每次读取的长度:" + len);
				// 解析内容
				if (isContinue) {
					// 针对头部信息,防止制定的字节一个byte[len]你不够,此处进行字节数组拼接
					if (headbyte == null) {
						headbyte = new byte[len];
						System.arraycopy(b, 0, headbyte, 0, len);

					} else {
						byte[] tmp = new byte[headbyte.length + len];
						System.arraycopy(headbyte, 0, tmp, 0, headbyte.length);
						System.arraycopy(b, 0, tmp, headbyte.length, len);
						headbyte = tmp;
						b = tmp;

					}

					for (int i = start_position; i < b.length; i++) {
						if (b[i] == '\r') {
							end_position = i;
							String data = new String(b, start_position, end_position - start_position);
							if (isFirstLine) {
								isFirstLine = false;
								System.out.println(data);
								String[] firstLineData = data.trim().split(" ");
								if (firstLineData.length != 3) {
									res.setStatus("999");
									return res;
								} else {
									res.setStatus(firstLineData[2]);
									res.setStatusNum(firstLineData[1]);
									res.setVersion(firstLineData[0]);
								}
							}
							// String data = new String(b, start_position,
							// end_position - start_position);
							if (data.contains("Content-Length")) {
								// System.out.println("----contlen"+data);
								contlen = Integer.parseInt(data.split(" ")[1]);
							}
							if (data.contains(":")) {
								String[] headsplit = data.split(":");
								res.getHeadMap().put(headsplit[0].trim(), headsplit[1].trim());
							}

							System.out.println("每次读取输出的内容:" + data);
							start_position = i + 2;
							i = i + 1;
							if (data.equals("")) {
								isContinue = false;
								System.out.println("内容准备读取,跳出循环准备全部去读");
								break;
							}

						}

					}
				}
				// 如果头结点已经读取完毕,则进行保留内存的内容结点
				if (isContinue == false) {

					if (context == null) {
						context = new byte[b.length - start_position];
						if (b.length - start_position > 0) {
							System.arraycopy(b, start_position, context, 0, b.length - start_position);
						}
						// 需要判断是否立即结束 ----针对于一次读完的情况,加入此判断,否则可能存在问题
						if (len < BYTELEN) {
							break;
						}
					} else {
						byte[] tmp = new byte[context.length + len];
						System.arraycopy(context, 0, tmp, 0, context.length);
						System.arraycopy(b, 0, tmp, context.length, len);
						context = tmp;
						System.out.println((context.length) + "-------------" + contlen);
						if (context.length == contlen) {// 表示数据读取完毕
							break;

						}
					}

				}

			}
			long endTime = System.currentTimeMillis();
			System.out.println("使用时间:" + (endTime - startTime));
			res.setResultSoapXml(new String(context));
			socket.shutdownInput();
			socket.shutdownOutput();
			is.close();
			is = null;
			socket = null;
			System.out.println("处理完毕");
		} catch (IOException e) {
			System.out.println(e);
		}

		return res;
	}

}



三、测试结果:
OK 200 HTTP/1.1
Server-->Microsoft-IIS/6.0
Cache-Control-->private, max-age=0
X-AspNet-Version-->2.0.50727
Content-Length-->838
Date-->Tue, 12 Dec 2017 15
X-Powered-By-->ASP.NET
Content-Type-->text/xml; charset=utf-8

<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><getSupportCityResponse xmlns="http://WebXml.com.cn/"><getSupportCityResult><string>合肥 (58321)</string><string>巢湖 (58326)</string><string>蚌埠 (58221)</string><string>安庆 (58424)</string><string>六安 (58311)</string><string>滁州 (58236)</string><string>马鞍山 (58336)</string><string>阜阳 (58203)</string><string>宣城 (58433)</string><string>铜陵 (58429)</string><string>淮北 (58116)</string><string>芜湖 (58334)</string><string>宿州 (58122)</string><string>淮南 (58224)</string><string>池州 (58427)</string></getSupportCityResult></getSupportCityResponse></soap:Body></soap:Envelope>

四、遇见问题





错误内容很明细,就是只能打印出消息头,消息体不能打印,然后过段时间连接重置,报错,当时还怀疑服务器没有返回,使用抓包工具后,发现数据是返回的,然后这个问题就困惑了好几天


关键问题:

read()会返回-1呢?答案是:当TCP通信连接的一方关闭了套接字时。【readLine底层应该也是这个类似方法】

     再次分析改过后的代码,客户端用到了read()返回-1这个条件,而服务端也用到了,只有二者有一方关闭了Socket,另一方的read()方法才会返回-1,而在客户端打印输出前,二者都没有关闭Socket,因此,二者的read()方法都不会返回-1,程序便阻塞在此处,都不往下执行,这便造成了死锁。

基本上确定了:webservice服务端并没有关闭输出的socket输入流,由于我们只是客户端,我们就无法控制了,处理的方式就是:
 
将inputStream流中读取完后【context-length:然后读取这个长度】,之后直接跳出再次读环节就可以了,具体就见代码了,有点小麻烦!!


五、此只是本人深入一点学习http协议吧,如果要模拟http请求建议httpclient,代码有问题,也欢迎大家指正!谢谢!!!

  
  • 大小: 130.2 KB
  • 大小: 28 KB
分享到:
评论

相关推荐

    java调用webservice.zip

    java调用webservicejava调用webservice.zipjava调用webservice.zipjava调用webservice.zipjava调用webservice.zipjava调用webservice.zipjava调用webservice.zipjava调用webservice.zipjava调用webservice.zipjava...

    socket多线程调用webservice服务实现系统对接

    利用socket thread dom4j log4j axis2 soap PBE加解密等相关技术实现的socket协议调用webservice服务。 由于银行后台核心系统普遍采用的是UNIX下C/C++的开发平台,如果需要调Web Service往往需要借助一些第三方的库...

    java使用XFire调用webService接口

    "Java 使用 XFire 调用 webService 接口" 在本文中,我们将学习如何使用 XFire 框架在 Java 中调用 webService 接口。XFIRE 是一个基于 Java 的开源框架,用于简化 Web 服务的开发和集成。下面,我们将通过一个简单...

    java android 调用webservice

    总结,Java Android调用Webservice涉及到网络请求、数据传输、解析和安全等多个环节,开发者需要了解HTTP协议,选择合适的Web服务类型,以及掌握相应的数据解析技术。通过合理利用第三方库和遵循最佳实践,可以提高...

    java axis 调用webservice服务端

    Java Axis调用WebService服务端是Java开发者在进行分布式系统交互时常见的一种技术实践。Axis是Apache软件基金会开发的一个开源项目,它提供了一种方便、高效的方式,使得Java应用程序能够作为客户端来消费或作为...

    C#调用JavaWebService

    调用WebService,最简单的办法当然是直接添加WEB引用,然后自动产生代理类,但是在调用JAVA的WebService时并没有这么简单,特别是对于SoapHeader的处理,通过C#添加Web引用方式访问JavaWebService的方法,除了string...

    java调用C++ webservice

    本话题主要探讨如何使用Java调用由C++实现的Web服务(Webservice)。在给出的描述中,提到了通过WSDL(Web Services Description Language)文件来实现这一目标。以下是关于这个主题的详细知识点: 1. **Web服务...

    java 调用 webService工具类

    JAX-WS提供了创建和消费SOAP WebService的API,包括`javax.jws.WebService`注解用于声明服务端点,以及`javax.xml.ws.Service`类用于客户端调用。本工具类可能利用了JAX-WS的一些核心功能来简化服务调用。 4. **...

    Java动态调用webService,axis2动态调用webService

    本文将深入探讨如何使用Axis2来动态地调用Web Service,并通过分析`WebServiceInvoker.java`这个文件来理解其实现原理。 1. **Java动态调用Web Service**: 在Java中,动态调用Web Service主要涉及到JAX-WS(Java ...

    java调用json参数的webservice

    在探讨Java调用带有JSON参数的WebService之前,我们首先需要了解几个关键的技术概念:Java、JSON以及WebService。 Java是一种广泛使用的编程语言,它具有面向对象、跨平台、多线程以及健壮性等特点。Java在企业级...

    java 调用 odi webservice

    Java 调用 ODI webservice 实现数据同步 Java 调用 ODI webservice 是实现数据同步的一种常见方式。ODI(Oracle Data Integrator)是一种数据集成平台,提供了webservice接口,允许用户通过webservice调用ODI方案...

    JAVA调用WEBSERVICE接口

    JAVA调用WEBSERVICE接口

    Java使用XFire调用WebService接口

    这篇博客“Java使用XFire调用WebService接口”显然是讨论如何利用XFire这个开源框架来与Web服务交互。 XFire是Apache CXF项目的前身,它提供了一种简单的方式来创建和消费SOAP Web服务。XFire的强项在于其轻量级和...

    JAVA 调用SAP SOAP webservice.docx

    JAVA 调用 SAP SOAP webservice 详解 在本文中,我们将详细介绍如何使用 JAVA 调用 SAP SOAP webservice,包括配置 SAP 登录信息、创建 java 项目、添加 web 服务客户端、生成 JAVA 类、调用接口等步骤。 配置 SAP...

    java 调用https webservice实例及axis包

    总的来说,使用Apache Axis调用HTTPS Web Service涉及到了Java的网络编程、SSL/TLS协议以及Web Service的原理。通过理解这些知识点,开发者可以构建安全、可靠的Web Service客户端应用。在实践中,务必关注安全性,...

    Java Axis 直接调用webservice 接口工具类

    Java Axis 直接调用webservice 接口工具类, 无需根据wsdl编译客户端,需要axis相关包,测试使用axis 1.4, 附demo引入axis包后直接可以测试;

    java调用webservice接口案例,service调用webservice接口

    java调用webservice接口案例,精简,service调用webservice接口案例;不用生成一堆代码,逻辑清晰

    java客户端调用webservice所调用的axis1.4包和方法调用

    本方法是用axis1.4技术,实现java客户端调用webservice。已经可实现过可行的,如果不行可加我QQ号302633进行详细解析。

    JAVA调用webservice并解析xml

    总结,调用Java中的Web服务并解析XML涉及到了Web服务的基础概念、Java的Web服务客户端创建、XML解析技术以及实际的调用与响应处理。熟练掌握这些知识点,能够帮助开发者有效地集成和利用各种Web服务资源。

    java调用webservice工程

    Java调用WebService工程是将Java应用程序与通过WebService接口提供的服务进行交互的过程。WebService是一种基于XML标准的、平台和语言无关的通信方式,它允许不同系统间的应用能够共享数据和服务。在Java中,我们...

Global site tag (gtag.js) - Google Analytics