您的位置:首页 > 理论基础 > 计算机网络

使用JavaSocket编写发送TCP请求的工具类

2017-09-29 16:42 267 查看
参考原博主文章:玄玉http://blog.csdn.net/jadyer

/**
* 使用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
*/
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 = new byte[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 static void main(String[] args) {
String aa = "FE7D1C85F93DDD307BF7F2B7F474E8471FEB14BEF85F40579613F535E87DE81D11EE8E4DA5DE4A3E642BE9BB5CDBDB44AB4B905453D7FF3A88D3F6AD066506C188D3F6AD066506C188D3F6AD066506C188D3F6AD066506C1
9d37
88D3F6AD066506C171C9E8C61254E9DE74C226EFB1D5991F4B7A691C6785A6A765F8D7EC64D49B656FDA4E896501F132462BAEE6B831DAE8B122B3EF54796F04AD5A163403091CC7B1A48BE8AC4E6656F00DBAC3DEEDD65288D3F6AD066506C188D3F6AD066506C1DD351A282E7AE76AA18BA4BE009EA2033A6754DBACBDF21C7BC39BFE45FF0F7A6563A0182C869AC43A91F7AC88EFD96A65F8D7EC64D49B656FDA4E896501F132594DAA0ECB1F44947B8D03C32494EB650C41903221754E40475DDE31DA50320FAC0FD33293F01A23E84591109D9E62FAD26D930E4BC20231C4E3FEB54979A4F188D3F6AD066506C188D3F6AD066506C188D3F6AD066506C1";
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 = "192.168.0.253";
String port = "80";
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("=============================================================================");

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐