情况是这样的,我作为C的客户端,与对方的java服务端通信。用socket收发xml报文。
流程是我这边发送一笔报文,对方经过业务处理之后,返回给我一笔报文,以xml形式发送(其实我觉得这个xml不重要,到最后都是转为字节流的形式发送)。
现在遇到的问题是这样的,我发送给对方的报文对方可以全部接收到,但是对方返回给我的报文我只能接收到一部分。
经过抓包发现,在对方发送给我一部分之后,对方发送了一个rst包过来,导致通信中断。
对方用telnet在win环境下模拟客户端发送报文,他可以全部接收返回的报文,所以怀疑是我这边C的客户端问题。
然后我这边用telnet测试,我这边在AIX环境下用telnet发送报文,与C客户端一样的,于是怀疑是网络问题。
但是对方用telnet在linux环境下模拟客户端发送报文,他也只能接收到一部分,因此,网络问题排除。
后来我这边用java写的客户端发送报文,又可以接收到全部的报文,所以,怀疑java下的socket通信与C之间存在差异,这个差异在java与telnet之间也存在。但是为什么在win下面的telnet可以成功接收?难道win的telnet和基于UNIX的telnet有什么区别?
求熟悉的人解答。
下面粘贴部分关键代码。
对方给的部分java服务端代码:
private void sendBackData(InputStream outputXML) { mLogger.info("Socket服务端准备向客户端返回数据。"); OutputStream outputStream = null; try { byte[] vbytes = new byte[1]; ByteArrayOutputStream vOutNoSTDByteArrayOutputStream = new ByteArrayOutputStream(); while (outputXML.read(vbytes) != -1) { vOutNoSTDByteArrayOutputStream.write(vbytes); } vOutNoSTDByteArrayOutputStream.flush(); vOutNoSTDByteArrayOutputStream.close(); byte[] tOutNoSTDbytes = vOutNoSTDByteArrayOutputStream .toByteArray(); InputStream tOutNoSTDStreamAnother = new ByteArrayInputStream( tOutNoSTDbytes); byte[] x2 = tOutNoSTDbytes; InputStream g_input2 = new ByteArrayInputStream(x2); tOutNoSTDStreamAnother = g_input2; // 获取文件大小 int fileLength; InputStream d = new ByteArrayInputStream(x2); for (fileLength = 0; d.read() != -1; fileLength++) ; mLogger.info("报文总长度:" + fileLength); int tPackHeadLength = fileLength; String tPackHeadLengthStr = null; PacketAnalyze tPacketAnalyze = new PacketAnalyze(); tPackHeadLengthStr = tPacketAnalyze.getBackHeadData(baseInfo, tPackHeadLength); // 增加包头信息 byte[] array = new byte[tPackHeadLengthStr.length()]; int m = 0; // 包体长度 byte arrayPackHeadLength[] = tPackHeadLengthStr.getBytes(); for (int i = 0; i < array.length; i++) { if (i < arrayPackHeadLength.length) { array[m] = arrayPackHeadLength[i]; } m++; } mLogger.info("包头总长度:" + tPackHeadLengthStr); outputStream = m_socket.getOutputStream(); outputStream.write(array); // 增加包体信息 // 增加socket别的方法 byte[] x = (new YBTFun()).INSToByteArray(tOutNoSTDStreamAnother); outputStream.write(x); mLogger.info("socket向客户端返回信息完毕。"); mLogger.info("交易完毕"); mLogger.info("****************************华丽的分行线************************"); } catch (IOException e) { mLogger.error("将信息返回客户端失败:" + e); } catch (MidplatException e) { mLogger.error("将信息返回客户端失败:" + e); } finally { try { outputStream.flush(); outputStream.close(); m_socket.close(); } catch (IOException e) { mLogger.error("关闭Socket和输出流失败"); } } }
C客户端代码(因为底层通信封装过的,所以我这边只贴出来自己写的,但是问题是一样的代码):
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <errno.h> #define LOCALFILE "1.xml" struct netinfo_t { char addr[16]; int iPort; }; int RecvBuffer(int tmpSocket,int* iLen,char* tmpBufferRecv) { int iRecvCount = 0; char strLen[7] = "\0"; int iCountAll = 0; int iOperaCount = 0; iRecvCount = recv(tmpSocket, strLen ,6 ,0); if(iRecvCount <= 0) { close(tmpSocket); return -1; } iRecvCount = atoi(strLen); *iLen = iRecvCount; /* if(0 != readn(tmpSocket, tmpBufferRecv, *iLen)) { perror("rec"); printf("error recv\n"); close(tmpSocket); return -1; } */ while(iCountAll < iRecvCount) { iOperaCount = recv(tmpSocket,tmpBufferRecv+iCountAll,iRecvCount-iCountAll,0); if(iOperaCount <= 0) { perror("rec"); printf("error recv\n"); close(tmpSocket); return -1; } iCountAll += iOperaCount; } return 0; } int SendBuffer(int tmpSocket,int iLen,char* tmpSendBuffer) { char strSendLen[10] = "\0"; int iOperaCount = 0; sprintf(strSendLen,"%08d",iLen); int iCountAll = 0; iOperaCount = send(tmpSocket, strSendLen, 8, 0); if(0 >= iOperaCount) { close(tmpSocket); return -1; } while(iCountAll < iLen) { iOperaCount = send(tmpSocket, tmpSendBuffer + iCountAll, iLen-iCountAll, 0); if(0 >= iOperaCount) { close(tmpSocket); return -1; } iCountAll += iOperaCount; } return 0; } int sockCnt(void *infor) { int iSock; int iOn = 1; struct sockaddr_in stClient; int iLen = sizeof(stClient); int iPort; struct netinfo_t *netinfor = (struct netinfo_t *)infor; int bufferLen; char tmpSendBuffer[20480] = "\0"; FILE *fp; int FILELen; int iReadCount = 0; int iRetCount = 0; char *pFileBuffer; iPort = netinfor->iPort; memset(&stClient, 0, iLen); stClient.sin_family = AF_INET; stClient.sin_addr.s_addr = inet_addr(netinfor->addr); stClient.sin_port = htons(iPort); if((iSock = socket(AF_INET, SOCK_STREAM, 0)) < 0){ printf("create socket error\n"); return -1; } /*set socket option*/ if (setsockopt(iSock, SOL_SOCKET, SO_REUSEADDR, &iOn, sizeof(iOn)) < 0) { printf("Socket Server Reuse Address Fail\n"); return -1; } /*connect call*/ if(connect(iSock, (struct sockaddr *)&stClient, iLen) < 0) { perror("connect:\n"); printf("connect remote server error!\n"); return -1; } if((fp = fopen(LOCALFILE, "rb")) == NULL) { printf("file open error!\n"); return -1; } fseek(fp, 0L, SEEK_END); FILELen = ftell(fp); fseek(fp, 0L, SEEK_SET); printf("---->file length:%d\n",FILELen); pFileBuffer = (char *) malloc(FILELen + 1); while (iReadCount < FILELen) { iRetCount = fread(pFileBuffer + iReadCount, sizeof(unsigned char), FILELen - iReadCount, fp); iReadCount += iRetCount; if(iRetCount < 0) { printf("fread error!\n"); fclose(fp); return -1; } } printf("---->file:%s\n",pFileBuffer); fflush(fp); pFileBuffer[FILELen] = 0x00; SendBuffer(iSock, FILELen, pFileBuffer); RecvBuffer(iSock, &bufferLen, tmpSendBuffer); printf("bufferLen[%d] tmpSendBuffer[%s] ----->tmpSendBuffer[%x]\n", bufferLen, tmpSendBuffer, tmpSendBuffer); close(iSock); return; }
我这边测试用的java客户端代码:
public String send() throws Exception { String rv = ""; InputStream is = null; String funcflag = res.getString("PackageHead"); String filename = res.getString("PackageFile"); try { is = new FileInputStream(filename); byte[] sendbuf = getBytes(is);// 整个交易信息 String headlength = ""; // 得到头长度 if (funcflag == null || funcflag.length() > 7) throw new Exception("获取交易码出错!"); headlength = fillRightStr(String.valueOf(sendbuf.length), 6, " "); headlength += fillRightStr(funcflag, 7, " "); byte[] sendhead = headlength.getBytes(CHARSET);// 发送报文的头部 byte[] send = new byte[sendbuf.length + sendhead.length];// 发送报文缓冲区 System.arraycopy(sendhead, 0, send, 0, sendhead.length);// 将头拷贝到发送报文中 System.arraycopy(sendbuf, 0, send, sendhead.length, send.length - sendhead.length);// 将报文体拷贝到发送报文中 ip = res.getString("YBTHost"); port = Integer.parseInt(res.getString("YBTPort")); System.out.println("发送数据到主机:" + ip + ", 端口:" + port); System.out.println("请求报文:"); System.out.println(new String(sendbuf, CHARSET)); // 新建Socket通信 Socket socket = new Socket(ip, port); // 通信输出字节流 OutputStream out = socket.getOutputStream(); out.write(send); out.flush(); // 开始接收数据 byte[] buf = new byte[1]; InputStream in = socket.getInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); while (in.read(buf) != -1) baos.write(buf); byte[] bytes = baos.toByteArray(); byte[] back = new byte[bytes.length - sendhead.length]; System.arraycopy(bytes, sendhead.length, back, 0, bytes.length - sendhead.length); baos.flush(); baos.close(); is.close(); rv = new String(back, "GBK"); } catch (Exception e) { throw new Exception(e); } return rv; } private String fillRightStr(String str, int length, String fill) { int fillLength = length - str.length(); for (int i = 0; i < fillLength; i++) str += fill; return str; }
抓包情况:
18:41:34.219385 IP local.50290 > server.8602: S 3262906674:3262906674(0) win 65535 <mss 1460> 18:41:34.241106 IP server.8602 > local.50290: S 1854668494:1854668494(0) ack 3262906675 win 5840 <mss 1460> 18:41:34.241128 IP local.50290 > server.8602: . ack 1 win 65535 18:41:35.826513 IP local.50290 > server.8602: P 1:53(52) ack 1 win 65535 18:41:35.846242 IP server.8602 > local.50290: . ack 53 win 5840 18:41:36.555608 IP local.50290 > server.8602: P 53:1611(1558) ack 1 win 65535 18:41:36.588355 IP server.8602 > local.50290: . ack 1513 win 8760 18:41:36.588555 IP server.8602 > local.50290: . ack 1611 win 8760 18:41:36.664539 IP server.8602 > local.50290: P 1:14(13) ack 1611 win 8760 18:41:36.664738 IP server.8602 > local.50290: R 14:14(0) ack 1611 win 8760
可以看到服务端返回reset包之后,通信终端。
麻烦各位看一下。
相关推荐
计算机网络实验中的Socket通信编程与传输协议分析是一个深入理解TCP/IP协议栈中传输层工作原理的重要实践环节。在这个实验中,学生们将通过编程实践来掌握Socket接口的使用,理解TCP的连接建立、数据传输和连接关闭...
在IT行业中,网络通信是至关重要的一个环节,TCP(Transmission Control Protocol)作为互联网协议栈中的主力,负责在两台计算机之间建立可靠的数据传输连接。在进行网络编程时,经常需要检查特定的TCP端口是否被...
7. **Socket编程**:Java的Socket类是网络编程的基础,它提供了一种在两台机器间建立可靠、双向通信的方法。在端口扫描器中,Socket用于尝试建立连接,通过异常处理来判断端口是否开放。 8. **并发处理**:为了提高...
Java端口扫描是一种技术,主要用于检测网络上的主机开放了哪些通信端口,这些端口是计算机服务对外提供功能的窗口。在本项目中,我们有一个名为"java端口扫描.zip"的压缩包,其中包含了一个Java编写的端口扫描小工具...
JAVA的`java.net.Socket`类用于创建TCP连接,`SocketInputStream`和`SocketOutputStream`用于读写数据。 4. **端口扫描原理**:端口扫描通常通过发送SYN包(TCP三次握手的一部分)来测试端口是否开放,如果收到SYN+...
Java的`java.net.Socket`和`java.net.DatagramSocket`类分别用于TCP和UDP的连接与通信。 在源代码中,我们可以预期包含以下几个关键部分: 1. **目标主机和端口范围的定义**:程序需要指定要扫描的主机IP地址和...
在本文中,我们将深入探讨这种异常的处理和分析,特别是与Java中的Socket通信相关的方面。 首先,`ConnectionResetException`是Java中与网络连接异常相关的错误类型,它通常在尝试读取或写入一个已经关闭或重置的...
在Java中实现端口扫描,可以使用`java.net.Socket`类或者`java.nio`包中的非阻塞I/O功能。以下是一个基本的TCP端口扫描器示例: ```java import java.io.IOException; import java.net.InetSocketAddress; import ...
以上就是关于“Java版端口扫描器”的核心知识点,涵盖了从基础的Java编程、Swing GUI设计到Socket网络通信和端口扫描原理等多个方面。通过学习和理解这个项目,开发者可以提升在网络编程和GUI开发方面的技能。
在IT领域,网络通信是核心部分之一,而端口扫描是网络管理员和安全专家常用的工具,用于检测远程或本地系统开放的服务和端口。本课程设计的主题是“利用多线程基于TCP扫描目的主机端口程序”,这涉及到计算机网络、...
开发者需要知道如何使用Java的Socket类或者OkHttp等库来实现TCP通信,同时处理连接建立、数据传输和连接关闭等过程。熟悉TCP协议的工作原理和特性,可以帮助开发者更有效地构建稳定、高效的网络应用。
TCP(Transmission Control Protocol)是一种面向连接的、...在Java网络编程中,理解TCP和T/TCP的工作原理至关重要,特别是对于开发涉及Socket通信的应用。掌握这些概念可以帮助开发者编写出更高效、更健壮的网络应用。
例如,在Python中,可以使用`os.system()`调用系统`ping`命令,或者使用`socket`库直接发送ICMP、TCP或UDP数据包。在Java中,可以使用`java.net.InetAddress.isReachable()`方法。对于更底层的操作,可能需要使用如C...
控制位包括 ACK、RST、SYN 和 FIN 等字段,分别用于确认应答、重置连接、建立连接和断开连接。 TCP 协议的必要性 为什么需要 TCP 协议?IP 层是不可靠的,它不能保证网络包的交付、顺序交付和数据的完整性。因此...
控制位包括 ACK、RST、SYN、FIN 等,ACK 表示确认应答的字段变为有效,RST 表示 TCP 连接中出现异常必须强制断开连接,SYN 表示希望建立连接,并在其“序列号”的字段进行序列号初始值的设定,FIN 表示今后不会再有...
- **Java**:跨平台,可以使用Java NIO进行端口扫描。 - **Go**:并发性能强,适合构建快速扫描工具。 4. **源码分析**: - 本示例可能包含用特定语言编写的端口扫描程序,涉及网络套接字编程,如创建socket,...