主要线程部分:import java.net.*;import java.io.*;import java.util.*;public class sendMsg extends Thread{Socket sok_cm=null;Vector vct_svrtocm=null;DataOutputStream dos_svrtocm=null;int int_sleeptime;public boolean b_stop=false;public sendMsg(Socket sok_cm,Vector vct_svrtocm,int int_sleeptime){

this.sok_cm=sok_cm;

this.vct_svrtocm=vct_svrtocm;

this.int_sleeptime=int_sleeptime;
}
private void openOS(){

try{
//sok_cm.setKeepAlive(true);

dos_svrtocm=new DataOutputStream(sok_cm.getOutputStream());

}
catch(IOException ioe){System.out.println("建立输出流出现异常:"+ioe.toString());}
//catch(SocketException se){System.out.println("KeepAlive:"+se.toString());}
}
private void sendtocm(){

synchronized(vct_svrtocm){

if (!vct_svrtocm.isEmpty()){ int n=vct_svrtocm.size();

System.out.println(n);

try{

//System.out.println(sok_cm.getSendBufferSize());

 /**
 System.out.println("old title:"+dos_svrtocm.size());
for(int i=0;i<n;i++){
  byte[] bya_temp=(byte[])vct_svrtocm.elementAt(i);
 
try{
 
dos_svrtocm.write(bya_temp,0,bya_temp.length);
 
System.out.println("send:"+i+" "+bya_temp.length );
 
  }
         catch(IOException ioe){System.out.println("dos.write:"+ioe.toString());}  
}
 
*/
//一次只发送一条

System.out.println("old title:"+dos_svrtocm.size());

dos_svrtocm.write((byte[])vct_svrtocm.firstElement());

System.out.println("new title:"+dos_svrtocm.size());

 dos_svrtocm.flush();
 
 System.out.println("flush");
 
 vct_svrtocm.removeElementAt(0);
 
}

catch(Exception e){System.out.println("chat_sendmsg"+e.toString());
e.printStackTrace();
b_stop=true;
}

}

}//end of synchronized
}
public void run(){

openOS();

while(true){

if(!b_stop){

sendtocm();

//System.out.println("**********sendtocm正在活动**********");


try{

Thread.sleep(int_sleeptime);
}
catch(InterruptedException ie){}

}
else{

try{

if (dos_svrtocm!=null){

dos_svrtocm.close();

dos_svrtocm=null;

//System.out.println("sendMsg关闭了输出流");
}
}
catch(IOException ioe){}

finally{break;} }
}System.out.println("消灭tcmc.chat.thread.sendMsg线程");
}
}
我认为是很标准的发送方法,到写到一定的字节数(并不确定写了多少),一执行到到了dos_svrtocm.write();就没有相应了。也没有异常抛出。

解决方案 »

  1.   

    应该是VC与Java之间的兼容问题,试试看,在结尾加个什么结束符(VC中自动加上的,当时java中没有)我用VB时出现过类似问题。结果是加个(10)字符就可以了,你试试看,祝你好运。
      

  2.   

    但是在这个项目的通讯协议里面没有结束符,只是从协议的某个字节来表明此协议+消息的长度,来收发消息的。这个结束符号VC中是那个char(0)吗?在java中可以用(byte)0来代替。但是我在协议的末尾(协议为定长)都补的是(byte)0。
    DataOutputStream在write()一定的字节数组后,就好像阻塞了一样,停在write()方法出不动了。我原来把收发消息做在了两个Thread里,现在有把他们都放在一个Thread里,还是由此现象。怎么回事?急切!!
      

  3.   

    我又进行了一些测试:发现小数据量时(几十个byte)候没有问题,但是大部分时候要发的都是800字节左右的数据,应该说800byte不是很大,但是为什么会出现这种情况?我的数据栈不会被填满了吧,但是我是一边向流里写数据然后flush()呀,栈怎么会这么快就填满?我即使1秒/条(800byte)时,都会堵死。
    还有就是flush()方法不是把现在流里的数据发送出去吗?flush()以后,流就空了。这时候数据应该到了ISO的更底层了,交给网卡去打包了,数据会不会堵在了网卡?我也不是太明白。看在我努力思考的分上,高手帮帮我!
      

  4.   

    以前,我用java做过一个通信程序也有socket阻塞现象,后来查明原因是:只发送数据而不接收数据,前面几个数据包可以出去,后面的数据包全部出不去,发生阻塞。不知道你的是否这个原因。
      

  5.   

    谢谢回答。
    我把收发消息现在做在了一个线程里面,在一个循环中:先向VC服务器发送数据,然后再用DataInputStream.read(byte[] b)数据,但是VC服务器并不是一定会给我发返回数据的,在协议中就是这么定的,所以设置sotime时间,超时后返回。我在测试的时候,正如您所说的确只是发送了数据,VC服务器并没有返回信息,但是我不太明白的是:照此道理一个套接字连接必须要实现数据的发和收才可以吗?我要是在应用中,只需要它的发数据功能怎么办?非给每一次发送后,在接受一个返回消息吗?再有Socket.shutdownOutput()和Socket.shutdownInput()这两个方法不就是可以关闭一个方向的流吗?如此要时关闭了一个方向的流,Socket也就完蛋了?
    真是让人感到奇怪呀!再次感谢,也许看到希望了。
      

  6.   

    在发送数据同时也应该接收数据,对方没有给我发返回数据,就是说自己接收数据的内容的长度为0,但不等于null。正因为有“读”这个动作,Java的系统底层的I/O的缓冲区有刷新的动作过程。我看过部分java的英文文档,但不全面,再加上自己的英文水平一般般,看了不太懂。大家有兴趣一起讨论一下吧!
      

  7.   

    谢谢,但是我把协议按照需要改了一下,每次发送数据都会受到返回数据,但是线向还是出现!有时发送了500多条,但是发送的数量有偏差,死掉。有时不到十条就死了。哎!~~~~
    上面您说的是不是要实现read()方法,即使read()不到数据,产生InterruptedException后返回?我就是这么写得呀?
    这种情况和网络环境有没有关系?我的网卡是10mb局域网,VC服务器是局域网的另一台机器。
      

  8.   

    用两个线程,一个循环收,一个循环发;记住线程要sleep
      

  9.   

    其实我一开始就是这么设计的。都是sleep(50);优先级是10,理论上20条/分。不算快。小数据量时,只发但是收到第4条返回消息就再也收不到了,只是在发送,到底发没法出去,不知道。这是从System.out看见的。还有就是收发写到一起,发小数据量时就可以,很正常。能发也能收。奇怪。
      

  10.   

    对不起!有做了测试,小数据量发送也不成功!!发送到700-800条,vc 服务器就没有返回消息了,我比较相信Vc端。
    痛苦呀!~~~~
      

  11.   

    你的程序我已经修正了,程序运行通过。14分钟发送3万条记录,中间过程不阻塞。
    给我一个Email地址,我把修正程序代码和辅助测试的程序代码给你发过去。
      

  12.   

    Thank you !
    [email protected]
    我要学习一下,必有重谢!
      

  13.   

    Thank you !
    [email protected]
    我要学习一下,必有重谢!
      

  14.   

    的确。正如lizicai的结果。但是这是在java环境内测试,但是我的服务器端是VC写的。会不会与此还有关系?
    只要与VC服务器通信,VC即便发返回消息,java端也是会被阻塞的。但是这是在局域网环境下的测试,java版本的测试是在一台机器上,数据其实并没有出去。和这个有没有关系?还请大家多多帮助!!
    再次感谢lizicai,必有重分向谢!!
      

  15.   

    adolfdi的程序的阻塞现象的原因应该是没有主动接收对方应答的内容而造成的。结果是缓冲区用满了后溢出,先是自己发出的信息对方没收到,跟着是自己也发不出的信息。Java的socket通讯是基于TCP/IP协议基础上的通讯,不会受到跨平台和其他的语言(例如vc,vb等)的产品而造成通讯影响。adolfdi的测试程序修改参数IP地址, 照样可以在广域网上运行。adolfdi的程序还有很多不完善的地方,希望好好修改。
      

  16.   

    问题是我已经主动接收了VC的应答消息,在接收不了几条后,就又阻塞了。
    还有就是缓冲区如何请空?flush()以后不就请空了吗?不知道理解的对不对,那又是如何被填满溢出的呢?
    我的程序中还有那些地方不完善,请Sir lizicai指正出来,我好学习一下。
    再次感谢Sir Lizicai。