我用Socket进行远程文件传输,但是在循环时总是差最后一点点就不传了,真郁闷!下面代码稍作配置就可以运行的。在readme.txt中说明的很详细。请各位帮我看看哦!
我的悬赏分没有了,真不好意思啊!还请各位不吝赐教啊!
[b]问题补充:[/b]
我改小了每次写入的大小,也没有用啊!
[b]问题补充:[/b]
在Eclipse中可以设置字符编码的。MyEclipse应该也有吧?不过我没有过MyEclipse啊!不好意思,麻烦各位了啊
[b]问题补充:[/b]
我在处理Socket端对数据的接收做了一个方法,具体在[code="java" color=#FF0000]// 得到去除头信息的字节流
readInfo = SoftwareProcessUtil.getInputStreamByte(in,
byteSize);[/code] 具体引用在SoftwareProcessUtil.java 中的 [code="java"]/**
*
* getInputStreamByte decription : 从Socket inputStream中得到去除头信息的字节数组
*
* @param in
* @param byteSize
* 需要读取的包含头信息的字节流的长度
* @return
*/
public static byte[] getInputStreamByte(InputStream input, Integer byteSize) {
// 设置已经读取数从去头信息开始
int readed = 0; // 已经读取数
// 头信息长度
int headSize = HTTP_HEAD_GET_INFO.getBytes().length;
// 初始化需要返回的数组
byte[] result = new byte[byteSize - headSize];
try {
int available = 0; // 可读数
if (available > (byteSize - readed)) {
available = byteSize - readed;
}
while (readed < byteSize) {
while (available == 0) {
// 等到有数据可读
available = input.available(); // 可读数
}
if (available > (byteSize - readed)) {
available = byteSize - readed; // 剩余数
}
if (available > SOCKET_INPUT_ARRAY_LENGTH) {
available = SOCKET_INPUT_ARRAY_LENGTH; // size-readed--剩余数
}
byte[] buffer = new byte[available];
int reading = input.read(buffer);
for (int n = 0; n < reading; n++) {
if ((readed + n) < headSize) {
continue;
}
result[readed + n - headSize] = buffer[n];
}
readed += reading; // 已读字符
}
} catch (IOException e) {
System.out.println("Read readLenData Error!");
}
System.out.println("SoftwareProcessUtil result length = "+ result.length);
return result;
}[/code]
[b]问题补充:[/b]
我在这块代码中的 public static final int BLOCK_SIZE = 1024; 只是1024个byte啊,并没有1024K啊
[b]问题补充:[/b]
我试过512个字节了,没有用,我在SoftwareProcessUtil.java中的public static byte[] getInputStreamByte(InputStream input, Integer byteSize)方法中修改了一下,修改后的代码如下:面的附件。我现在问题是:最后一次读取服务器的传输的数据流时,他总是有最后一个字节读不到,所有在Client端就会死在getInputStreamByte方法中的[code="java"]while (available == 0) {
// 等到有数据可读
available = input.available(); // 可读数
}[/code]这儿。郁闷死了
[b]问题补充:[/b]
我在SoftwareProcessUtil.java 中做了一点点修改。代码如下:[code="java"]package edu.sjtu.infosec.ismp.manager.virus.software.util;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import edu.sjtu.infosec.ismp.manager.virus.software.exception.SoftwareManagerException;
/**
*/
public class SoftwareProcessUtil {
public static void main(String[] args) {
System.out.println(splitString("CXDOEER LENGTH:324 ", "LENGTH"));
System.out.println(HTTP_HEAD_GET_INFO.getBytes().length);
}
/**
/**
/**
/**
/**
/**
/**
/**
/**
@return
*/
public static byte[] spliceDownloadLengthHeadInfo(int size) {
return addByte(HTTP_HEAD_GET_INFO + "LENGTH:" + size);
}
/**
/**
/**
/**
/**
/**
/**
@return
*/
public static Map getNameAndLengthMap(byte[] downloadInfos) {
// 需要解析的参数为空的情况
if (downloadInfos == null || downloadInfos.length <= 0) {
return null;
}
// 初始化返回结果
Map result = new HashMap();
// 转换成字符串
String info = new String(downloadInfos);
// 以分号分隔
String[] nameAndLengths = info.split(";");
// 当需要下载的软件名和软件大小为空时
if (nameAndLengths == null || nameAndLengths.length <= 0) {
return null;
}
for (int i = 0; i < nameAndLengths.length; i++) {
// 得到每一个名字和大小的组合:name:xxx.exe&size:123213
String nameAndLength = nameAndLengths[i];
// 得到以"&"分割后的字符串组
String[] temp = nameAndLength.split("&");
// 得到文件名name:xxx.exe
String nameStr = temp[0];
// 得到文件大小size:123213
String sizeStr = temp[1];
// 如果软件名和软件大小为空的情况
if (nameStr == null || sizeStr == null
|| sizeStr.trim().length() <= 0) {
continue;
}
nameStr = nameStr.substring(nameStr.indexOf(":") + 1, nameStr
.length());
sizeStr = sizeStr.substring(sizeStr.indexOf(":") + 1, sizeStr
.length());
// 如果软件名和软件大小为空的情况
if (nameStr == null || sizeStr == null
|| sizeStr.trim().length() <= 0) {
continue;
}
// 得到文件大小
Long size = new Long(sizeStr.trim());
// 把软件名和软件大小设置到返回结果Map中
result.put(nameStr, size);
}
// 如果需要返回的结果为空的情况
if (result.isEmpty()) {
return null;
}
return result;
}
/**
/**
@throws SoftwareManagerException
*/
public static Map processSoftwareInfos(String softwareInfos,
List prefixnames) throws SoftwareManagerException {
// 如果输入的需要处理的字符串为空的情况
if (softwareInfos == null || softwareInfos.trim().length() < 0) {
return null;
}
// // 得到本地软件分发父文件夹中的所有xml的名字
// List names = softwareManagerService
// .getAllSoftwareNames(parentFolderAbsolutePath);
// 对需要处理的字符串以分号分割
String[] tempInfos = softwareInfos.split(";");
// 分割处理的结果
if (tempInfos == null || tempInfos.length <= 0) {
return null;
}
// 初始化需要返回的结果
Map result = new HashMap();
// 临时存储变量
List softwareNames = new ArrayList();
// 对分割的结果集进行循环 name:xxx&size:12312
for (int i = 0; i < tempInfos.length; i++) {
// 得到每个可以下载的Xml的详细信息
// name:xxx&size:12312;
String definiteInfos = tempInfos[i];
if (definiteInfos == null || definiteInfos.trim().length() <= 0) {
continue;
}
// 把得到的单个xml详细信息以&分割
String[] definiteInfo = definiteInfos.split("&");
if (definiteInfo == null || definiteInfo.length < 1) {
continue;
}
// 得到软件名name:xxx
String nameStr = definiteInfo[0];
// 得到文件大小size:123213
String sizeStr = definiteInfo[1];
// 如果软件名和软件大小为空的情况
if (nameStr == null || sizeStr == null
|| sizeStr.trim().length() <= 0) {
continue;
}
nameStr = nameStr.substring(nameStr.indexOf(":") + 1, nameStr
.length());
sizeStr = sizeStr.substring(sizeStr.indexOf(":") + 1, sizeStr
.length());
// 如果软件名和软件大小为空的情况
if (nameStr == null || sizeStr == null
|| sizeStr.trim().length() <= 0) {
continue;
}
// 加入临时比较变量集合中
softwareNames.add(nameStr);
// 加入需要返回的结果集合中
result.put(nameStr, new Long(sizeStr.trim()));
}
// 如果需要下载的软件集合为空的情况
if (result.isEmpty()) {
return null;
}
// 本地父目录里的软件信息列表为空的情况
if (prefixnames == null || prefixnames.isEmpty()) {
return result;
}
// 循环本地的父文件夹中的所有xml文件名
for (int i = 0; i < prefixnames.size(); i++) {
// 得到本地父目录中不含后缀名的文件名
String prefixname = prefixnames.get(i);
// 循环服务器端可以下载的软件信息列表
for (int j = 0; j < softwareNames.size(); j++) {
// 得到可以下载的文件名
String softwareName = softwareNames.get(j);
// 可以下载的文件名中没有后缀名的情况"."
if (softwareName.lastIndexOf(".") == -1) {
// 文件名不符合标准的情况下
result.remove(softwareName);
continue;
}
// 如果本地父目录中的软件前缀名和服务器可以下载的软件的前缀名一致的情况
if (prefixname.equals(softwareName.substring(0, softwareName
.lastIndexOf(".")))) {
result.remove(softwareName);
break;
}
}
}
// 可以下载的软件信息为空的情况
if (result.isEmpty()) {
return null;
}
// 返回可以下载的软件名
return result;
}
/**
/**
@return
*/
public static byte[] getInputStreamByte(InputStream input, Integer byteSize) {
// 设置已经读取数从去头信息开始
int readed = 0; // 已经读取数
// 头信息长度
int headSize = HTTP_HEAD_GET_INFO.getBytes().length;
// 初始化需要返回的数组
byte[] result = new byte[byteSize - headSize];
try {
int available = 0; // 可读数
if (available > (byteSize - readed)) {
available = byteSize - readed;
}
while (readed < byteSize) {
while (available == 0) {
// 等到有数据可读
available = input.available(); // 可读数
}
if (available > (byteSize - readed)) {
available = byteSize - readed; // 剩余数
}
if (available > (BLOCK_SIZE+HTTP_HEAD_GET_INFO.getBytes().length)) {
available = (BLOCK_SIZE+HTTP_HEAD_GET_INFO.getBytes().length); // size-readed--剩余数
}
byte[] buffer = new byte[available];
int reading = input.read(buffer);
for (int n = 0; n < reading; n++) {
if ((readed + n) < headSize) {
continue;
}
result[readed + n - headSize] = buffer[n];
}
available = 0;
readed += reading; // 已读字符
}
} catch (IOException e) {
System.out.println("Read readLenData Error!");
}
System.out.println("SoftwareProcessUtil result length = "+ result.length);
return result;
}
}
[/code]
[b]问题补充:[/b]
谢谢walsh的热心回复,虽然你没有帮我实质性的解决问题,但是我还是要感谢你的帮助!谢谢了!
那可能就是你的方法写的不对了。
楼主,今天我刚解决了一个朋友的提问,你可以看看。
[url]http://www.iteye.com/problems/23772[/url]
你看是不是每次传的数据太多了,如果多接收方就不可能接收完整,这个如果都在自己机子上测试可能会没有问题,但是放到网络上,就会出现。
解决办法是,每次限制每个包最大为512个字节,然后再传,传到对方之后,再合在一块,就行了。
[code="java"]/**
* 对文件进行分割的每块的大小 : 10M
*/
public static final int BLOCK_SIZE = 1024;
/**
* Socket inputStream 每次传输的数组长度
*/
public static final int SOCKET_INPUT_ARRAY_LENGTH = BLOCK_SIZE
+ HTTP_HEAD_GET_INFO.getBytes().length;[/code]
[color=red]楼主上面是你写的代码,我大致看了看,你吧每次传的数据大小设置为512个自己,多传几次没有什么,你如果传的多,在客户端就已经把数据截断了,服务器端当然就收不到数据了。[/color]
楼主写的代码,注释做的还不错。唯一不好的就是,不能直接导到Myeclipse中。
[size=medium]不好意思,上面误写了两个字,是把数据包的大小设置为512个字节。你可以做个试验,先设置为512个字节,然后再设置为1024个字节。[/size]
楼主可以单步测试一下,看看究竟是由于什么原因引起的,是由于阻塞,还是由于接收方的socket关闭了,如果不是上述原因,
我觉得还是因为每次传的数据太多的原因,数据包小一点,512个字节就可以了,然后在传一段时间sleep一会,别一下次就把所有的包都扔到网上了。
[quote]我在这块代码中的 public static final int BLOCK_SIZE = 1024; 只是1024个byte啊,并没有1024K啊 [/quote]
改为512个字节,试试。