使用JavaSocket编写发送TCP请求的工具类
来源:互联网 发布:全能星战 知乎 编辑:程序博客网 时间:2024/05/21 14:03
原创:http://blog.csdn.net/jadyer/article/details/8788303
使用JavaSocket编写发送TCP请求的工具类
分类: JavaSE2013-04-11 14:56190人阅读评论(0)收藏举报
javasockettcphttpmina
- package com.jadyer.util;
- import java.io.ByteArrayOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.net.InetSocketAddress;
- import java.net.Socket;
- import java.util.HashMap;
- import java.util.Map;
- /**
- * 使用JavaSocket编写发送TCP请求的工具类
- * @see 类似的有一个Mina工具类:http://blog.csdn.net/jadyer/article/details/8088068
- * @see 欲查询Scoket的有关属性:http://blog.csdn.net/jadyer/article/details/8788272
- * @create Apr 5, 2013 9:25:34 PM
- * @author 玄玉<http://blog.csdn.net/jadyer>
- */
- public class TCPUtil {
- private TCPUtil(){}
- /**
- * 发送TCP请求
- * @see 本方法默认的连接超时和读取超时均为30秒
- * @see 编码与解码请求响应字节时,均采用双方约定的字符集,即本方法的第四个参数reqCharset
- * @param IP 远程主机地址
- * @param port 远程主机端口
- * @param reqData 待发送报文的中文字符串形式
- * @param reqCharset 该方法与远程主机间通信报文的编码字符集(编码为byte[]发送到Server)
- * @return localPort--本地绑定的端口,reqData--请求报文,respData--响应报文,respDataHex--远程主机响应的原始字节的十六进制表示
- */
- public static Map<String, String> sendTCPRequest(String IP, String port, String reqData, String reqCharset){
- Map<String, String> respMap = new HashMap<String, String>();
- OutputStream out = null; //写
- InputStream in = null; //读
- String localPort = null; //本地绑定的端口(java socket, client, /127.0.0.1:50804 => /127.0.0.1:9901)
- String respData = null; //响应报文
- String respDataHex = null; //远程主机响应的原始字节的十六进制表示
- Socket socket = new Socket();//客户机
- try {
- socket.setTcpNoDelay(true);
- socket.setReuseAddress(true);
- socket.setSoTimeout(30000);
- socket.setSoLinger(true,5);
- socket.setSendBufferSize(1024);
- socket.setReceiveBufferSize(1024);
- socket.setKeepAlive(true);
- socket.connect(new InetSocketAddress(IP, Integer.parseInt(port)),30000);
- localPort = String.valueOf(socket.getLocalPort());
- /**
- * 发送TCP请求
- */
- out = socket.getOutputStream();
- out.write(reqData.getBytes(reqCharset));
- /**
- * 接收TCP响应
- */
- in = socket.getInputStream();
- ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
- byte[] buffer = newbyte[512];
- int len = -1;
- while((len=in.read(buffer)) != -1){
- bytesOut.write(buffer, 0, len);
- }
- /**
- * 解码TCP响应的完整报文
- */
- respData = bytesOut.toString(reqCharset);
- respDataHex = formatToHexStringWithASCII(bytesOut.toByteArray());
- } catch (Exception e) {
- System.out.println("与[" + IP +":" + port + "]通信遇到异常,堆栈信息如下");
- e.printStackTrace();
- } finally {
- if (null!=socket && socket.isConnected() && !socket.isClosed()) {
- try {
- socket.close();
- } catch (IOException e) {
- System.out.println("关闭客户机Socket时发生异常,堆栈信息如下");
- e.printStackTrace();
- }
- }
- }
- respMap.put("localPort", localPort);
- respMap.put("reqData", reqData);
- respMap.put("respData", respData);
- respMap.put("respDataHex", respDataHex);
- return respMap;
- }
- /**
- * 通过ASCII码将十进制的字节数组格式化为十六进制字符串
- * @see 该方法会将字节数组中的所有字节均格式化为字符串
- * @see 使用说明详见<code>formatToHexStringWithASCII(byte[], int, int)</code>方法
- */
- private static String formatToHexStringWithASCII(byte[] data){
- return formatToHexStringWithASCII(data,0, data.length);
- }
- /**
- * 通过ASCII码将十进制的字节数组格式化为十六进制字符串
- * @see 该方法常用于字符串的十六进制打印,打印时左侧为十六进制数值,右侧为对应的字符串原文
- * @see 在构造右侧的字符串原文时,该方法内部使用的是平台的默认字符集,来解码byte[]数组
- * @see 该方法在将字节转为十六进制时,默认使用的是<code>java.util.Locale.getDefault()</code>
- * @see 详见String.format(String, Object...)方法和new String(byte[], int, int)构造方法
- * @param data 十进制的字节数组
- * @param offset 数组下标,标记从数组的第几个字节开始格式化输出
- * @param length 格式长度,其不得大于数组长度,否则抛出java.lang.ArrayIndexOutOfBoundsException
- * @return 格式化后的十六进制字符串
- */
- private static String formatToHexStringWithASCII(byte[] data,int offset, int length){
- int end = offset + length;
- StringBuilder sb = new StringBuilder();
- StringBuilder sb2 = new StringBuilder();
- sb.append("\r\n------------------------------------------------------------------------");
- boolean chineseCutFlag = false;
- for(int i=offset; i<end; i+=16){
- sb.append(String.format("\r\n%04X: ", i-offset));//X或x表示将结果格式化为十六进制整数
- sb2.setLength(0);
- for(int j=i; j<i+16; j++){
- if(j < end){
- byte b = data[j];
- if(b >=0){ //ENG ASCII
- sb.append(String.format("%02X ", b));
- if(b<32 || b>126){//不可见字符
- sb2.append(" ");
- }else{
- sb2.append((char)b);
- }
- }else{ //CHA ASCII
- if(j == i+15){//汉字前半个字节
- sb.append(String.format("%02X ", data[j]));
- chineseCutFlag = true;
- String s = new String(data, j,2);
- sb2.append(s);
- }else if(j == i&&chineseCutFlag){ //后半个字节
- sb.append(String.format("%02X ", data[j]));
- chineseCutFlag = false;
- String s = new String(data, j, 1);
- sb2.append(s);
- }else{
- sb.append(String.format("%02X %02X ", data[j], data[j +1]));
- String s = new String(data, j, 2);
- sb2.append(s);
- j++;
- }
- }
- }else{
- sb.append(" ");
- }
- }
- sb.append("| ");
- sb.append(sb2.toString());
- }
- sb.append("\r\n------------------------------------------------------------------------");
- return sb.toString();
- }
- }
下面是测试代码
- public staticvoid main(String[] args) {
- String reqData = "0003721000510110199201209222240000020120922000069347814303000700000813``中国联通交费充值`为号码18655228826交费充值100.00元`UDP1209222238312219411`10000```20120922`chinaunicom-payFeeOnline`UTF-8`20120922223831`MD5`20120922020103806276`1`02`10000`20120922223954`20120922`BOCO_B2C```http://192.168.20.2:5545/ecpay/pay/elecChnlFrontPayRspBackAction.action`1`立即支付,交易成功`";
- String IP = "127.0.0.1";
- String port = "9901";
- String reqCharset = "GB18030";
- Map<String, String> respMap = sendTCPRequest(IP, port, reqData, reqCharset);
- System.out.println("=============================================================================");
- System.out.println("请求报文如下");
- System.out.println(respMap.get("reqData"));
- System.out.println("=============================================================================");
- System.out.println("响应报文如下");
- System.out.println(respMap.get("respData"));
- System.out.println("=============================================================================");
- System.out.println("响应十六进制如下");
- System.out.println(respMap.get("respDataHex"));
- System.out.println("=============================================================================");
- }
下面是控制台输出
- //控制台输出如下
- //=============================================================================
- // 请求报文如下
- // 0003721000510110199201209222240000020120922000069347814303000700000813``中国联通交费充值`为号码18655228826交费充值100.00元`UDP1209222238312219411`10000```20120922`chinaunicom-payFeeOnline`UTF-8`20120922223831`MD5`20120922020103806276`1`02`10000`20120922223954`20120922`BOCO_B2C```http://192.168.20.2:5545/ecpay/pay/elecChnlFrontPayRspBackAction.action`1`立即支付,交易成功`
- // =============================================================================
- // 响应报文如下
- // 00015800000000订单结果通知:商户系统未成功接收到通知,需要继续通知 6717356649614827173120130405201628201304051`
- // =============================================================================
- // 响应十六进制如下
- //
- // ------------------------------------------------------------------------
- // 0000: 30 30 30 31 35 38 30 30 30 30 30 30 30 30 B6 A9 | 00015800000000订
- // 0010: B5 A5 BD E1 B9 FB CD A8 D6 AA 3A C9 CC BB A7 CF | 单结果通知:商户系
- // 0020: B5 CD B3 CE B4 B3 C9 B9 A6 BD D3 CA D5 B5 BD CD | ?统未成功接收到通
- // 0030: A8 D6 AA 2C D0 E8 D2 AA BC CC D0 F8 CD A8 D6 AA | ?知,需要继续通知
- // 0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
- // 0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
- // 0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
- // 0070: 00 00 36 37 31 37 33 35 36 36 34 39 36 31 34 38 | 67173566496148
- // 0080: 32 37 31 37 33 31 32 30 31 33 30 34 30 35 32 30 | 2717312013040520
- // 0090: 31 36 32 38 32 30 31 33 30 34 30 35 31 60 | 1628201304051`
- // ------------------------------------------------------------------------
- // =============================================================================
- //
- 使用JavaSocket编写发送TCP请求的工具类
- 使用JavaSocket编写发送TCP请求的工具类
- 使用JavaSocket编写发送TCP请求的工具类
- 使用JavaSocket编写发送HTTP_POST请求的工具类
- 使用JavaSocket编写发送HTTP_POST请求的工具类
- 使用Java原生API编写发送HTTP_POST请求的工具类
- 使用Java原生API编写发送HTTP_POST请求的工具类
- 使用Java原生API编写发送HTTP_POST请求的工具类
- 使用php的socket发送tcp请求
- TCP/UDP简单介绍及JavaSocket的使用
- 04网络请求工具类的编写
- 发送请求工具—Advanced REST Client的使用
- 发送http请求工具类
- javaSocket编程TCP
- javaSocket TCP框架比较
- JavaSocket实现TCP编程
- httpClient 用于发送HTTP请求的工具类
- httpClient 用于发送HTTP请求的工具类
- 黑马程序员------java学习笔记之正则表达式
- android谁动了我的内存
- Eclipse中安装Visual Editor
- 【Linux基础】数据存储优先顺序
- 比酒量 - 蓝桥杯
- 使用JavaSocket编写发送TCP请求的工具类
- 庆贺杭州、广州、大连分公司相继成立,TechExcel发展驶入快车道
- java中的重载
- 关于Ubuntu下apt的一些用法及和yum的比较
- 使用BackgroundWorker组件
- socket学习杂记
- 关于B树 、B+树、B*树
- C++和CSharp增加AutoCAD的菜单menu
- 开源项目之Android imifirewall(防火墙)