还有一个问题,我在外部怎么得知有异常发生???run 函数是 线程类的 特有的,不能抛处异常,也就是说,我用 jsp 来调用的时候, 没法判断是否有异常发生,只有通过 socket.isInputShutdown()socket.isClosed()socket.isConnected()socket.isOutputShutdown()socket.getKeepAlive()  socket 这些函数来判断过虑错误发生
有其他好的方法吗?
???????

解决方案 »

  1.   

    socket传输是否结束,我记得传输数据流数据的DataInputStream(应该是这个类名吧?)类的write方法传输完后会返回一个int值,从而判断是否传输成功,同样,对应DataOutputStream其read方法则可以返回一个long值,是接收到的数据流byte[]的长度,好像为-1则传输失败
    像你使用的这种情况,那几个输出肯定是要等write或flush完成以后才会执行的,按理说若无返回值,传输失败的话就会报异常的说
    btw:JSP调试,若使用Jbuilder的话,你可以将异常在后台输出阿,也同样可以看到的
    我很久没做socket这些东西了,手头上现在也没资料,不知道如上所说对你是否有帮助
      

  2.   

    1.首先我查了 DataInputStream 的write 方法 返回值是 void
    2.另外对方给出的数据结构 是 byte[] ,于是好像只查到 
    protected InputStream in = null;
    protected OutputStream out = null;
    能够实现
    3. 在vc 的CSocket 中的 send 倒是可以返回一个值来判断发送是否正确,
    但java中就是没找到这种类似的方法。只有从异常来判断 :(((
    4. 还有关于 KeepAlive 的问题,因为是java 对接 c 的socket, 要是c 判断连接断开了,而java认为还连接着,发送时候 是否会抛出异常。
    ?????
    请高手指点!!!!
      

  3.   

    不可能阿
    我清清楚楚记得我1年前做过一个socket通讯的,对方是VC,我当时用以接受数据的流是可以返回一个long类型判断是否传输成功,难道是接受时才有的?我都忘了
      

  4.   

    socket write时外界只有在异常中抛出应用级异常
      

  5.   

    socket的写操作缺省是阻塞方式的,你调用write返回,就证明已经发送完成(当然有异常就是发送 失败了)。
      

  6.   

    如果打印出了 for(int i=0;i<len;i++) System.out.print(s[i]); 和 System.out.print("ok"); 没有打印出e.printStackTrace();,ep.printStackTrace(); 能够说明 out.write(s,0,len); out.flush(); 已经完成吗????
    郁闷的问题,根本没发调试!!!!可以说明write已经完成了,如果在write的过程中出现错误,就会有IOException抛出,你可以在这里面进行一些关闭连接的操作。
      

  7.   

    如果真的想调试有异常的情况,你可以加上Thread.sleep(5000);等待5秒,然后马上把服务器关掉,这样write就有IOException
      

  8.   

    我是在对接一个别人的socket 端口, 按照上面的分析,已经发送了数据,
    但对方说没收到,又没在一个地方,只有听对方说没收到我怀疑是socket 断了,当java 就是不出现异常, write 函数也没有返回值
      

  9.   

    我把代码贴出来:请大家看看 到底是那里出错了连接类
    =======================
    package com.softwife;import java.io.*;
    import java.net.*;
    import java.util.*;public class Connection {  protected Socket socket = null;
      ReadThread readThread = new ReadThread();
      WriteThread writeThread = new WriteThread();
      
      protected InputStream in = null;
      protected OutputStream out = null;
      
      public static final int PING_TIME = 10 * 1000;
      public static final boolean verboseMode = true;  public Connection(Socket asocket) {
        socket = asocket;
      }
      
      public void send(Object obj) {
        send(obj.toString());
      }
      
      public void send(byte s[]) {
    System.out.println(new String(s));
    writeThread.send(s);
      }
      
      /**
      * attempts to connect and perform any handshaking required to establish communications.
      */
      public boolean connect() { 
        try {
          // experimental
          //socket.setSoTimeout(PING_TIME);   in = socket.getInputStream();
      out = socket.getOutputStream();
          if (!handshake()) throw new IOException("Faking this");
        } catch (IOException e) {
          closeSocket();
          return false;
        }
        return true;
      }
          
        
      /**
      * starts the asynchronous read/write threads.
      * call this after connect()
      */
      public void start() {
        readThread.start();
        writeThread.start();
      }
      
      /**
      * perform any handshaking required. in/out have already been setup.
      * return false to abort.
      * override in descendants
      */
      public boolean handshake() throws java.io.IOException {
        return true;
      }
      
      /**
      * override in descendants
      */
      public void onRead(byte s[]) { }
     
      /**
      * override in descendants
      */ 
      public void onClose() { }
      
      public synchronized void closeSocket() {
        try {
    System.out.println(socket.isInputShutdown()+"== isClosed="+socket.isClosed()+" ==isConnected="+socket.isConnected()+" ==isInputShutdown"+socket.isOutputShutdown()+" ==getKeepAlive="+socket.getKeepAlive() );
    socket.close(); 
    } catch (IOException e) { }
      }
        
    private class ReadThread extends Thread {
      
      public void run() {
    byte[] buf = new byte[1024];
    int i=0;
    while(true) {
    //if(++i>100) break;
    int iLength = 0;
    byte len[] = new byte[4]; //这组数据的长度
    try { 
    if ( in.read( len, 0,4 ) != -1 ){
    iLength = ((int)len[0]) | (((int)len[1])<<8) | (((int)len[2])<<16) | (((int)len[3])<<24) ;
    if(in.read(buf, 0, iLength-4) != -1){
    onRead(buf);
    }
    }
    } catch (IOException e) { 
    System.out.println("readTheadClose");
    closeSocket();
    break;
    }    
    }
    onClose();
      }}  // of ReadThreadprivate class WriteThread extends Thread {
      
      Vector outBuffer = new Vector();
      
      public synchronized void send(byte s[]) {
        outBuffer.addElement(s);
        notifyAll();
      }  public void run() {
        try {      
            while (true) {
    byte[] s = getNextSendObject();
    if (s == null) {
     // out.write((byte)0); out.flush();  
    } else {
      int len = ((int)s[0]) | (((int)s[1])<<8) | (((int)s[2])<<16) | (((int)s[3])<<24) ;
      for(int i=0;i<len;i++) System.out.print(s[i]);
      System.out.println(socket.isInputShutdown()+"==okokoisClosed="+socket.isClosed()+" ==isConnected="+socket.isConnected()+" ==isInputShutdown"+socket.isOutputShutdown()+" ==getKeepAlive="+socket.getKeepAlive() );
      out.write(s,0,len); out.flush();
      System.out.print("ok");
    }
            }      
        } catch (IOException e) {   
    e.printStackTrace();
    closeSocket();
        }  catch (Exception ep) {   
    ep.printStackTrace();
    closeSocket();
        } 
        
      }  private synchronized byte[] getNextSendObject() {
        if (outBuffer.size() == 0) {
          try { wait(PING_TIME); } catch (InterruptedException e) { }
        }
        // if still empty, return null
        if (outBuffer.size() == 0) return null;    Object obj = outBuffer.elementAt(0);
        outBuffer.removeElementAt(0);
        return (byte[])obj;
      }  
    } // of WriteThread}
      

  10.   

    下面是是一个 短信管理类
    ================================
    package com.softwife.sms;
    import com.softwife.*;
    import java.net.*;
    import java.util.*;
    import java.text.*;
    import sun.io.*;public class SMSManager {

    private static Object initLock = new Object();
        private static String className = "com.softwife.sms.SMSManager";
        private static SMSManager manager = null;
    private static SMSConnection connection = null; public static SMSManager getInstance() {
           
            if (manager == null) {
                synchronized(initLock) {
                    if (manager == null) {
                        try {
                            Class c = Class.forName(className);
                            manager = (SMSManager)c.newInstance();
                        }
                        catch (Exception e) {
                            System.err.println("不能装载类 " + className );
                            e.printStackTrace();
                            return null;
                        }
                    }
                }
            }  return manager;
        }
    private SMSManager(){
    try {
    Socket socket = new Socket(getHost(), getBasePort());
    socket.setKeepAlive(true);
    connection = new SMSConnection(this, socket);
    } catch (Exception e) {
    e.printStackTrace();
    System.out.println("不能连接到这个端口");
    return;
    } if (!connection.connect()) {
    System.out.println("Rejected: Try again");
    return;
    }
       
    connection.start();
    login();
    }

    private String getHost(){ return "www.softwife.com"; }
    private int getBasePort(){ return 7760; } private synchronized void login()
    {
    String SPName = "softwife", SPPassword="softwife", SPType="sp";
    byte pData[] = new byte[1024]; int iCount = 0 , i;
    int iCommandID = 0x1;
    byte command[] = new byte[4];
    command[3] = (byte)( (iCommandID & 0xff000000) >>> 24);
    command[2] = (byte)( (iCommandID & 0x00ff0000) >>> 16);
    command[1] = (byte)( (iCommandID & 0x0000ff00) >>> 8);
    command[0] = (byte)( (iCommandID & 0x000000ff) );

    byte name[] = SPName.getBytes();
    int nameLen = SPName.length() + 1 ;

    byte password[] = SPPassword.getBytes();
    int passwordLen = SPPassword.length() + 1;

    byte type[] = SPType.getBytes();
    int typeLen = SPType.length() + 1;

    iCount = 4*2 + nameLen + passwordLen + typeLen;
    byte len[] = new byte[4];
    len[3] = (byte)( (iCount & 0xff000000) >>> 24);
    len[2] = (byte)( (iCount & 0x00ff0000) >>> 16);
    len[1] = (byte)( (iCount & 0x0000ff00) >>> 8);
    len[0] = (byte)( (iCount & 0x000000ff) ); //数据的长度
    for(i=0; i<4; i++){
    pData[i] = len[i];
    }
    //指令代码
    for(i=0; i<4; i++){
    pData[i+4] = command[i];
    }
    //账号
    for(i=0; i<nameLen-1; i++){
    pData[i+8] = name[i];
    }
    pData[8+nameLen-1] = 0;
    //密码
    for(i=0; i<passwordLen-1; i++){
    pData[i+8+nameLen] = password[i];
    }
    pData[8+nameLen+passwordLen-1] = 0;
    //类型
    for(i=0; i<typeLen-1; i++){
    pData[i+8+nameLen+passwordLen] = type[i];
    }
    pData[8+nameLen+passwordLen+typeLen-1] = 0;

    //for(i=0; i<iCount; i++) System.out.print("_"+pData[i]);
    connection.send(pData);

    }
          public synchronized void send(String strSource, String strDest, String strMessage, int freeTyep, int freeValue)
       throws Exception 
    {

              try{
        
    byte pData[] = new byte[1024]; int iCount = 0 , i;
    int iCommandID = 0x2;

    //指令
    byte command[] = new byte[4];
    command[3] = (byte)( (iCommandID & 0xff000000) >>> 24);
    command[2] = (byte)( (iCommandID & 0x00ff0000) >>> 16);
    command[1] = (byte)( (iCommandID & 0x0000ff00) >>> 8);
    command[0] = (byte)( (iCommandID & 0x000000ff) );

    //付费类型
    byte type[] = new byte[4];
    type[3] = (byte)( (freeTyep & 0xff000000) >>> 24);
    type[2] = (byte)( (freeTyep & 0x00ff0000) >>> 16);
    type[1] = (byte)( (freeTyep & 0x0000ff00) >>> 8);
    type[0] = (byte)( (freeTyep & 0x000000ff) );

    //付费数量
    byte value[] = new byte[4];
    value[3] = (byte)( (freeValue & 0xff000000) >>> 24);
    value[2] = (byte)( (freeValue & 0x00ff0000) >>> 16);
    value[1] = (byte)( (freeValue & 0x0000ff00) >>> 8);
    value[0] = (byte)( (freeValue & 0x000000ff) );

    //源号码
    byte source[] = strSource.getBytes();
    int sourceLen = source.length + 1;

    //目的号码
    byte dest[] = strDest.getBytes();
    int destLen = dest.length + 1;

    //短信内容
    byte[] msg = strMessage.getBytes();
    int msgLen = msg.length + 1;

    //数据流的长度
    iCount = 4*4 + sourceLen + destLen + msgLen;
    byte len[] = new byte[4];
    len[3] = (byte)( (iCount & 0xff000000) >>> 24);
    len[2] = (byte)( (iCount & 0x00ff0000) >>> 16);
    len[1] = (byte)( (iCount & 0x0000ff00) >>> 8);
    len[0] = (byte)( (iCount & 0x000000ff) );

    for(i=0; i<4; i++){
    pData[i] = len[i];
    }
    for(i=0; i<4; i++){
    pData[i+4] = command[i];
    }
    for(i=0; i<4; i++){
    pData[i+8] = type[i];
    }
    for(i=0; i<4; i++){
    pData[i+12] = value[i];
    } for(i=0; i<sourceLen-1; i++){
    pData[i+16] = source[i];
    }
    pData[16+sourceLen-1] = 0; for(i=0; i<destLen-1; i++){
    pData[i+16+sourceLen] = dest[i];
    }
    pData[16+sourceLen+destLen-1] = 0; for(i=0; i<msgLen-1; i++){
    pData[i+16+sourceLen+destLen] = msg[i];
    }
    pData[16+sourceLen+destLen+msgLen-1] = 0; connection.send(pData);
      } catch(Throwable e) {
    e.printStackTrace();
    throw new Exception("发送短信时出现错误!");
      } 
    }    public synchronized void handleCommand(byte cmd[])
        {
    try {
    int iCommandID = 0, i;
    byte command[] = new byte[4]; //指令 for(i=0; i<4; i++) command[i] = cmd[i];
    iCommandID = ((int)command[0]) | (((int)command[1])<<8) | (((int)command[2])<<16) | (((int)command[3])<<24) ;
    byte ok[] = new byte[4];
    switch( iCommandID ){
    case 0x80000001: //登陆成功
    int loginOK;
    for(i=0; i<4; i++) ok[i] = cmd[i+4];
    loginOK = ((int)ok[0]) | (((int)ok[1])<<8) | (((int)ok[2])<<16) | (((int)ok[3])<<24) ;
    if( loginOK >0 ) System.out.println("^_^,登陆成功!");

    break;
    case 0x80000002: //回应短消息格式
    int sendOK;
    for(i=0; i<4; i++) ok[i] = cmd[i+4];
    sendOK = ((int)ok[0]) | (((int)ok[1])<<8) | (((int)ok[2])<<16) | (((int)ok[3])<<24) ;
    //if( sendOK >0 ) System.out.println("^_^,发送成功!");
    System.out.println("^_^,发送成功!NO="+sendOK); break;
    case 0x3: //接收短信
    String sourceNO , destNO , message ;
    byte srcByte[] = new byte[30], destByte[] = new byte[30], msgByte[] = new byte[300];
    i=0;
    while(cmd[i+4] != 0) { srcByte[i] = cmd[i+4]; i++; }
    i++;
    while(cmd[i+4] != 0) { destByte[i] = cmd[i+4]; i++; }
    i++;
    while(cmd[i+4] != 0) { msgByte[i] = cmd[i+4]; i++; }

    sourceNO = new String(srcByte);
    destNO = new String(destByte);
    message = new String(msgByte);

    System.out.println("sourceNO="+sourceNO+"   destNO="+destNO+"  message="+message);
    break;
    default: 
    System.out.println("sourceNO 错 !!!!");
    //throw new RuntimeException("Don't know how to handle this"); } } catch (Exception e) {
    e.printStackTrace();
    System.err.println("错误的数据!");
    return;
    }  
        }    public void shutdown() {
    connection.closeSocket();
    }
    }
      

  11.   

    java中好多对socket的操作都是用异常来判断的,如read方法的Timeout,感觉到它将Exception当作一种正常的处理机制了。
        write方法也没有判断是否写结束的方法,你可以用java专门写一个server的接受程序,看它到底有没有收到数据.
        read方法中虽然能够得到读入的字节数来判断有没有结束,但如碰到timeout就没办法了。
        我在写java的http的通信问题时也碰到不少的问题,大家可以多交流一下,感觉用java写socket通信的人不是很多。   My Email:[email protected]