服务端采用JAVA编写,客户端是C,都是运行在同一台机器上,OS是LINUX
如果客户端第一次发送的数据很大,那么就会出现connection reset这个异常
可是如果第一次发送比较少,那么不会出现这个异常一旦出现这个异常,那么客户端再次发送的数据,就不能接收到了服务端:
我启动了两个线程,
一个是专门用于监听接收客户端的数据,
另外一个是专门用于处理接收到的数据,监听接收到的数据的线程代码如下:
public class ThreadRcvMsg
{
    public static boolean bExitThread = false; // 退出线程标志    static ServerSocket servsock;
    
    public static final int QUIT_SLEEP_TIME = 5000;     public ThreadRcvMsg()
    {
        try
        {
            servsock = new ServerSocket(GlobalData.serviceAlarmPort);
            /*设置端口重用,当上次绑定失败后,下次绑定仍能成功*/
            servsock.setReuseAddress(true);
            
        }
        catch (IOException e)
        {
            WebuiLog.writeDebugLog("Can not create ServerSocket:"
                            + e.toString());
            return;
        }
        // 创建线程,并启动它们
        new Handler(servsock).start();
    }
        public static CommonResult quitThreadRcvMsg()
    {
        bExitThread = true; //退出标记为TRUE
        
        // 发送消息给自己,退出告警接收线程
        String exitMsg = "Begin to exit.";
        byte[] data = exitMsg.getBytes();
        
        SocketClient socket = null;           
            
        socket = new SocketClient(GlobalData.localInnerIpAddr, 
                        GlobalData.serviceAlarmPort);
        
        if (null == socket)
        {
            WebuiLog.writeDebugLog("Send exit message error");        
            return null;
        } 
        // send msg
        CommonResult sendResult = socket.sendNotRev(data);
        
        try
        {
            Thread.sleep(QUIT_SLEEP_TIME);
        }
        catch (Exception e)
        {
            WebuiLog.writeDebugLog("Sleep error:"
                            + e.getLocalizedMessage());
        }        
        return sendResult;     
        
    }
}
class Handler extends Thread
{
    final static int RCV_LEN = 284; // 每次接受数据的长度7个int    ServerSocket servsock;
        Handler(ServerSocket socket)
    {
        super();
        servsock = socket;
    }    MgmtMsg dataFlowIntoMsg(byte[] into)
    {
        return new MgmtMsg(into);
    }    public void run() 
    {
        int j = 0;
        byte[] data = new byte[RCV_LEN];
        // 等待一个连接
        
        while (true)
        {
            Socket clientsocket = null;
            try
            {                 
                if (ThreadRcvMsg.bExitThread)
                {
                    if (!servsock.isClosed())
                    {
                        servsock.close();
                    }
                    WebuiLog.writeDebugLog("Alarm thread exit in loop.");
                    break; // 退出线程
                }               
                
                // 等待下一个连接
                
                if (servsock.isClosed())
                {
                       break;
                }
                //clientsocket.setReuseAddress(true);
                clientsocket = servsock.accept();
               
                BufferedInputStream in = new BufferedInputStream(clientsocket
                                .getInputStream());
            
                while(in.read(data) > 0)
                {
//                     //收到退出消息
                    if (true == ThreadRcvMsg.bExitThread)
                    {
                        if (null != servsock)
                        {
                            servsock.close();
                        }    
                        
                        break;
                    }
                    synchronized (GlobalData.alarmMgmtMutex)
                    {
                      GlobalData.alarmList.add(this.dataFlowIntoMsg(data));
                      j++;
                      WebuiLog.writeDebugLog("send alarm j is : " + j);
                    }
                  
                    
                }
                
            }
            catch (IOException all)
            {
                WebuiLog.writeDebugLog("Thread handle error:"
                                + all.toString());
            }
            finally
            {
                try
                {
                    clientsocket.close();
                }
                catch(IOException e)
                {
                    WebuiLog.writeDebugLog("Close alarm socket error:" + e.toString());
                }
            }
           
        }
    }
}处理接收到的数据的线程如下:
public class AlarmThread implements Runnable
{
    private static boolean bExitThread = false; // 退出线程标志
    public static int i = 0;
    public AlarmThread()
    {
        
    }
    
    MgmtMsg dataFlowIntoMsg(byte[] into)
    {
        return new MgmtMsg(into);
    }
    
    public void run()
    {
       MgmtMsg data = null;
        while(!ThreadRcvMsg.bExitThread)
        {
            synchronized (GlobalData.alarmMgmtMutex)
            {
                data = null;
                if (ThreadRcvMsg.bExitThread)
                {
                    break;
     

解决方案 »

  1.   

    很难说你的问题出在什么位置不过建议你改改程序,不要用那么多的static方法和变量,尤其是多线程
    网络处理也要修改一下首先没有看到你的报文头处理部分。你怎么知道一个数据报有多大呢?只是无畏的在那里read,可是每一个报文的起点和终结点怎么知道
    还有,你用来接收的data长度是固定的,而数据长度是可变的,怎么进行数据合并呢?我没仔细看,不过感觉你是把收到的数据直接进行处理,也就是说read一次就把数据交给处理方法处理,却不关心数据是不是都收到了。而且每次收到数据并交付处理后data也不清空,如果第一次收到了100个数据,第二次收到了50个,但你的data里面其实前100位都不为0,你的处理方法怎么知道这是哪次收到的数据呢。
      

  2.   

    你把byte[] data = new byte[RCV_LEN];放到while循环里面去,然后把data长度扩大看看最好加上报文头,用来描述每次数据长度
      

  3.   

    我接受数据和处理数据是两个线程啊
    他们是加锁处理的啊
    所以,不是你说的接受到数据,就立即进行处理的data,我是从socket里面读取的,如果这次socket关闭了之后,那么data就没有了吧
    需要清空么?
    该如何清空呢?谢谢
      

  4.   

    看看这段
    while(in.read(data) > 0)
                    {
    //                     //收到退出消息
                        if (true == ThreadRcvMsg.bExitThread)
                        {
                            if (null != servsock)
                            {
                                servsock.close();
                            }    
                            
                            break;
                        }
                        synchronized (GlobalData.alarmMgmtMutex)
                        {
                          GlobalData.alarmList.add(this.dataFlowIntoMsg(data));
                          j++;
                          WebuiLog.writeDebugLog("send alarm j is : " + j);
                        }
                      
                        
                    }在
    while(in.read(data) > 0)
    的时候读取数据,读到后交给
    dataFlowIntoMsg(data)处理
    如果一次读取完毕应该没有问题,但如果一次没有读完呢?
    假设data=new byte[1024];
    第一次读取了1024个byte,之后再读第二次。假设读取了64个字节,你还是调用dataFlowIntoMsg(data)处理,那么你怎么知道第二次只有64个字节呢?或者说你怎么知道整个数据包一共只有1024+64个字节而不是1024+1024个呢?另外,我仔细看了一下你的代码,dataFlowIntoMsg()方法其实是返回一个类,传入的参数变成MgmtMsg实力放到队列准备处理。我不知道你的MgmtMsg是怎么做的,如果只是将data作为一个变量储存,那非常可怕。你队列里所有MgmtMsg节点的data变量实际上指向的都是同一个实例,第二次读取的时候就会改变以前放到队列中的数据。(只是猜测)当然这些不一定就是问题所在,不过确实是一个很严重的问题。建议你在调用dataFlowIntoMsg(data)后重新data=new byte[REC_LEN]一下,给他一个新的对象。
      

  5.   

    以前做过利用SOCKET通信的应用,发现数据包长度是有限制的,因为时间急迫,无法深究,只能测试出一个最大的长度。楼主可以查查SOCKET发包的限制,简单点就象我那样,测出一个目前最大可能的长度,然后拆包之后再发。
      

  6.   

    另外,楼主是在同一个机器上进行,这属于实验吗?
    如果是实验,建议还是在不同的机器上进行更贴近实际情况。
    如果不是实验,用SOCKET通信似乎太绕了点。
      

  7.   

    hehe
    是同一台机器上的啊
    数据是一次最多284个字节
    这个是客户端和服务端确定好了的
    难道
      synchronized (GlobalData.alarmMgmtMutex)
                        {
                          GlobalData.alarmList.add(this.dataFlowIntoMsg(data));
                          j++;
                          WebuiLog.writeDebugLog("send alarm j is : " + j);
                        }
    这里,我用GlobalData.alarmList.add(this.dataFlowIntoMsg(data));
    这个有错么?