- 浏览: 8693 次
- 性别:
- 来自: 成都
-
最新评论
一、写这篇记录的原因:
最近看了一些关于关于socket模拟文件服务器的文章或者视频,客户端通过浏览器访问,服务端通过socket去实现,学习之下了解到就是向socket发送制定格式的内容【http协议】,然后服务端进行解析,返回相关的数据,于是就想肯定要可以使用socket模拟调用webservice【webservice就是http协议+soap报文通过tcp协议来传输】,当然了使用httpclient去模拟发送get/post请求最方便,不过也是自己对http协议深入理解【原来的理解就知道http协议是什么样的,但是具体发送的啥内容也模糊】
二、直接贴代码:
1.调用部分
2.Response对象定义
3.核心处理部分[调用+解析]
三、测试结果:
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,代码有问题,也欢迎大家指正!谢谢!!!
最近看了一些关于关于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,代码有问题,也欢迎大家指正!谢谢!!!
相关推荐
使用`Socket`类可以创建客户端和服务端的网络连接。 **41. P2P传送文件** 点对点(P2P)文件传输通常涉及到直接在网络上的多个节点之间建立连接和交换数据。可以使用UDP协议或TCP协议实现。 **42. 加密技术** 加密...
wdaaaaaaaaaafwawfw
scratch少儿编程逻辑思维游戏源码-十字鸭子.zip
Android移动应用开发_ViewFlow自定义控件CircleFlowIndicator指示器网络图片加载缓存自动循环滚动手势滑动交互_横向循环平滑滚动广告条Banne
前端开发_基于jQuery和EasyUI框架_企业级Web应用UI组件库与后台管理系统模板_提供GPL开源版本和商业授权版本的双重授权模式_适用于快速构建响应式管理后台和复杂数据可
《C++编程实例100篇》是一本深入实践、极具价值的编程教程,它针对C++编程语言提供了丰富的实例,旨在帮助读者更好地理解和掌握C++的各项特性与编程技巧。这本书的经典之处在于它将理论与实践相结合,通过100个精心设计的编程实例,覆盖了C++的各个核心领域,包括基础语法、面向对象编程、模板、异常处理、STL(标准模板库)等。 我们来探讨C++的基础语法。C++是C语言的增强版,它保留了C语言的高效性和灵活性,并引入了类、对象和继承等面向对象编程概念。基础语法包括变量声明、数据类型、运算符、控制结构(如if语句、for循环、while循环)、函数的定义和调用等。在实例中,你可能会遇到如何编写简单的程序,如计算两个数的和,或者实现一个简单的猜数字游戏。 C++的面向对象编程是其一大特色。通过类和对象,你可以构建复杂的软件系统。类是对象的蓝图,它定义了对象的属性和行为。实例化一个类,就是创建一个具体的对象。继承允许你创建新的类,这些类从现有的类派生,共享其属性和方法,同时可以添加新的功能。多态性是面向对象的另一个关键特性,它使得不同类型的对象可以对同一消息作出不同的响应。这些概念在实例中会以各种形式展现,例如设计一个图形界面的类层次,或实现一个简单的模拟游戏。 接下来是模板,C++的模板功能让代码更加通用,可以处理不同类型的数据。模板分为函数模板和类模板,前者可以创建泛型函数,后者可以创建泛型类。通过模板,你可以编写出高效且灵活的代码,比如实现一个通用的排序算法。 异常处理是C++中用于处理程序运行时错误的机制。当程序出现异常情况时,可以抛出一个异常,然后在适当的点捕获并处理这个异常。这使得代码能够优雅地处理错误,而不是让程序崩溃。实例中可能会有涉及文件操作或网络通信时可能出现的异常处理示例。
scratch少儿编程逻辑思维游戏源码-忍者无限跑者.zip
少儿编程scratch项目源代码文件案例素材-战斗机游戏.zip
手工DIY行业_微信小程序云开发_手工坊预约管理系统_基于腾讯云开发技术的手工DIY行业线上线下结合解决方案_包含手工项目展示预约管理签到核销数据统计等完整功能_支持后台时段设置人
内容概要:本文档汇总了FFmpeg工具的多个实用命令示例,涵盖音频和视频处理的各个方面。包括但不限于:音频采样率转换、音频格式转为raw、查询音频文件时长与音量检测、调整音频音量大小、改变音频播放速度、视频逆序播放(针对无音频视频)、精准视频片段截取、音频片段截取、视频与音频合并处理、调整视频宽高比等。每个命令都提供了具体的参数设置方法; 适合人群:音视频编辑爱好者、多媒体处理领域的初学者或有一定经验的技术人员; 使用场景及目标:①在音频处理方面,可以完成从格式转换到音质调整的任务;②在视频处理上,能够实现基本的剪辑操作如切割、翻转、合并等;③为用户提供了一站式的解决方案,帮助用户快速掌握FFmpeg命令行工具的基本用法,提高工作效率; 阅读建议:本指南以命令实例为主,建议读者结合实际需求选择相应的命令进行尝试,在实践中理解各个参数的作用并灵活运用。
一、毕业设计的技术背景和设计依据 计算机硬盘驱动器作为一种存储数据信息的设备,在目前的计算机系统中起着不可替代的作用,读写的快慢对整个计算机系统的性能无疑占有重要地位。硬盘式电子计算机磁记录机构中最为精密的一类微机电系统设备,它对振动的敏感性是由其结构决定的,而其控制尚未很好的解决,针对硬盘展开建模及控制有着重要的实际应用价值。 二、毕业设计的任务 现代硬盘一般有 1 - 5 个盘片,以常见的 3.5 英寸硬盘为例,盘片直径约为 95mm,厚度约为 0.635mm。磁头数量通常与盘片数量相关,每面盘片有一个磁头,比如一个 3 盘片的硬盘就有 6 个磁头。缓存大小可能为 32MB、64MB 或 128MB 等,如某普通硬盘缓存为 64MB,电机功率一般在 2 - 5W,像转速为 7200RPM(转每分钟)的电机功率约 3W。数据写入时,磁头在电机带动下,以平均寻道速度约 10 - 15m/s 定位磁道。以一块顺序写入数据的硬盘为例,当写入连续大文件,如 1GB 的视频文件时,在 SATA3.0 接口下,理论传输带宽为 6Gb/s(约 750MB/s),实际可达 500 - 600MB/s。读取时,磁头感应盘片磁场变化,如读取小文件(1MB 大小),若磁头寻道距离平均为 1000 个磁道,每次寻道时间约 8 - 12ms,读取速度会因寻道而下降到 10 - 20MB/s。 本设计选取硬盘驱动器作为研究对象,假设电机扭矩为 0.3N・m,盘片转动惯量为 0.003kg・m²,轴承摩擦力矩为 0.03N・m。在稳定旋转阶段,转速波动范围设为额定转速的 ±0.5%,即 ±36RPM。首先通过对该系统分析建立了其物理模型,然后针对以音圈电机作为伺服机构的硬盘磁头定位伺服系统的性能要求,对音圈电机的控制设计采用三种控制器方案,即极点配置法、PID控制方法、线性二次型调节器方法,分别比较分
scratch少儿编程逻辑思维游戏源码-猫猫冲刺.zip
大数据处理_全文搜索引擎_ElasticSearch中文发行版_基于最新稳定版ElasticSearch预集成中文分词插件及常用配置的开箱即用解决方案_专为中文开发者优化的免配置高
离散数学_逻辑演算系统_真值表生成器_主范式计算器_最简范式求解器_王浩算法实现_等值演算工具_命题逻辑分析平台_基于Web的交互式逻辑运算系统_用于离散数学教学与研究的综合性逻辑
商业智能_SpringBoot_MQ_AIGC_React_智能数据分析_可视化图表_自动分析_数据集处理_用户诉求解析_数据降本增效_基于人工智能的商业智能分析平台_通过自然语言
少儿编程scratch项目源代码文件案例素材-爪猫小车.zip
少儿编程scratch项目源代码文件案例素材-拽猫挥剑.zip
kuishou68_neteaseMusic_32152_1745866029873
少儿编程scratch项目源代码文件案例素材-种族叛徒.zip
scratch少儿编程逻辑思维游戏源码-色彩交换.zip