请教入门的SOCKET文件传输效率问题。
ybhzf 2014-03-05 09:37:36 在传输过程中发现效率很低,本地局域网100mb网络只能用到5%的网络带宽,不知道是何缘故,同样的机器同样的网络使用其他IM工具传输效率可用到60-90%的带宽。
传输的28.rar文件8mb,用时2分钟。
期间尝试过加大两端的read缓存大小,或者加大socket双方的接收和发送缓存大小,效果均不佳。尝试过的相关设置如下:
this.st.setTrafficClass(0x10);
this.st.setPerformancePreferences(0, 1, 2);
this.st.setTcpNoDelay(true);//关闭优化算法
this.st.setReceiveBufferSize(this.packsize);
客户端代码如下:
InputStream is=null;
BufferedInputStream bis=null;
byte[] b=null;
int zj=0;
Socket st=null;
OutputStream os=null;
BufferedOutputStream bos=null;
try
{
st=new Socket();
st.connect(new InetSocketAddress("127.0.0.1", 5000));
os=st.getOutputStream();
bos=new BufferedOutputStream(os);
b=new byte[1024*1024*5];
is=new java.io.FileInputStream("28.rar");
bis=new BufferedInputStream(is);
while((zj=bis.read(b))!=-1)
{
bos.write(b,0,zj);
}
bos.flush();
}
finally
{
b=null;
try
{
if (bos !=null) bos.close();
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
bos=null;
}
try
{
if (os !=null) os.close();
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
os=null;
}
try
{
if (bis !=null) bis.close();
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
bis=null;
}
try
{
if (is !=null) is.close();
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
is=null;
}
try
{
if (st !=null && !st.isClosed()) st.close();
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
st=null;
}
}
服务端代码如下:
public class YServer
{
// 默认监听端口
public static final int port = 5000;
// 最大监听数量
public static final int maxport = 10;
// 默认操作超时时间(毫秒单位)
public static final int timeout = 0;
//默认文件存放目录
public static String filedir="f:/temp/";
/**
*
*/
public YServer()
{
// TODO Auto-generated constructor stub
}
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws Exception
{
// TODO Auto-generated method stub
ServerSocket ss = null;
InetSocketAddress isa = null;
Socket st = null;
try
{
//接收参数文件存放目录
if (args !=null && args.length>0)
{
if (args.length !=1) throw new Exception ("目录参数只能指定为1个!");
YServer.filedir=args[0];
}
if (YServer.filedir==null || YServer.filedir.trim().equals(""))
{
throw new Exception ("必须指定文件存放目录!");
}
else
{
YServer.filedir=YServer.filedir.trim();
if (YServer.filedir.endsWith("/") || YServer.filedir.endsWith("\\"))
{
}
else
{
YServer.filedir+="/";
}
File f=null;
try
{
f=new File(YServer.filedir);
if (!f.isDirectory())
{
throw new Exception ("指定的【"+YServer.filedir+"】不是一个目录!");
}
if (!f.canRead() || !f.canWrite())
{
throw new Exception ("指定的【"+YServer.filedir+"】目录没有读写权限!");
}
}
finally
{
f=null;
}
}
// 设置IP地址和端口
isa = new InetSocketAddress(YServer.port);
ss = new ServerSocket();
// 设置超时
ss.setSoTimeout(YServer.timeout);
// 绑定端口和最大连接数,ss=new ServerSocket(YServer.port,YServer.maxport);
ss.bind(isa, YServer.maxport);
// 循环接受应答
while (true)
{
// 得到连接入的网络连接
st=ss.accept();
if (st !=null)
{
//交给线程处理连接上的网络连接
new Thread(new YTrans(st,Charset.forName("GBK"))).start();
}
st=null;
// 线程休息,避免CPU 100%
Thread.sleep(500);
}
}
finally
{
isa = null;
try
{
if (st !=null && !st.isClosed())
{
st.close();
}
}
finally
{
st = null;
}
try
{
if (ss != null && !ss.isClosed())
{
ss.close();
}
}
finally
{
ss = null;
}
}
}
}
public class YTrans implements Runnable
{
/*
* 连接上的客户端
*/
private Socket st = null;
/*
* 字符集
*/
private Charset charset = null;
/*
* 客户端IP地址
*/
private String InetAddress = null;
/*
* 客户端端口
*/
private int port = 0;
/*
* 网络输入流
*/
private InputStream is = null;
/*
* 网络输出流
*/
private OutputStream os = null;
/**
* 数据包拆包大小
*/
private final int packsize = 1024*1024*5;
/**
* 是否为首次登录
*/
private boolean firstflag = false;
private FileOutputStream fs = null;
private BufferedOutputStream bfs = null;
// 默认构造函数
public YTrans()
{
}
/**
* 可初始化参数的构造函数
*
* @param st
* 连接上的客户端
* @param charset
* 字符集
*/
public YTrans(Socket st, Charset charset)
{
super();
this.st = st;
this.charset = charset;
}
/**
* @return the st 返回连接上的客户端
*/
public Socket getSt()
{
return st;
}
/**
* @param st
* the st to set 设置连接上的客户端
*/
public void setSt(Socket st)
{
this.st = st;
}
/**
* @return the charset 返回处理字符集
*/
public Charset getCharset()
{
return charset;
}
/**
* @param charset
* the charset to set 设置处理字符集
*/
public void setCharset(Charset charset)
{
this.charset = charset;
}
/**
* 业务处理逻辑
*
* @return
*/
private boolean Handle()
{
// 数据包总长度
int blen = 0;
// 临时数据对象
byte[] b = null;
try
{
// 网络连接对象为空
if (this.st == null) return false;
// 字符集编码为空
if (this.charset == null) return false;
// 网络没有连接
if (!this.st.isConnected()) return false;
// 获取网络输入输出流
if (this.is == null)
{
this.is = this.st.getInputStream();
}
if (this.is == null) return false;
this.os = this.st.getOutputStream();
if (this.os == null)
{
if (this.os == null) return false;
}
// 处理业务逻辑
b = null;
b = new byte[this.packsize];
// 读取输入流
while (true)
{
// 读取网络数据
blen = this.is.read(b);
// 判断是否读取到数据
if (blen == -1)
{
break;
}
}
// 使用后清理读取数组
b = null;
return true;
}
catch (Exception es)
{
es.printStackTrace();
return false;
}
finally
{
b = null;
}
}
@Override
public void run()
{
// TODO Auto-generated method stub
try
{
while (true)
{
if (!this.Handle()) break;
Thread.sleep(100);
}
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
try
{
if (this.bfs != null)
{
this.bfs.close();
}
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
this.bfs = null;
}
try
{
if (this.fs != null)
{
this.fs.close();
}
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
this.fs = null;
}
try
{
if (this.is != null)
{
this.is.close();
}
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
this.is = null;
}
try
{
if (this.os != null)
{
this.os.close();
}
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
this.os = null;
}
try
{
if (this.st != null && !this.st.isClosed())
{
this.st.close();
}
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
st = null;
}
System.out.println(new Date());
}
}
}