我现在已经写好了一个服务端的socket  主要完成的功能是当客户端发出登陆请求等请求的时候  予以响应    也就是当接收到客户端的数据包时,被动的发回响应数据包
那么,  现在我应该如何写,才能通过调用指定的方法来发送指定数据包呢?

解决方案 »

  1.   

    服务器端accept,客户端连接进来后,socket是双向可通信的。此时,服务器端用outputstream发送,客户端用InputStream接收就行了。
      

  2.   

    我来详细的说一遍: 关键代码如下
    服务器端  ServerSocket ss= new ServerSocket(端口号 如1555); //创建ServerSocket对象 
    有啦ss 在调用ss的accept方法返回一个Socket对象   Socket s=ss.accept();  写到这一步 服务器就阻塞到这里啦 一直等待客服端连接他    
    OutputStream os=s.getOutputStream();//向客户端发送信息
    BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(os));

    bw.write("服务器连接上.....");客服端 Socket s=new Socket("localhost",端口号);//这个端口号一定要与服务器的端口号相同
     通过s 得到一个inputstream对象  InputStream is=s.getInputStream(); 有啦InputStream 我们就可以通过bufferedReader读取服务器给客户端发来的信息    BufferedReader br=new BufferedReader
     (new nputStreamReader(is));  String s=br.readLine();//s就是服务器发来的信息
    其实说透啦  主要就是通过Socket类的getOutputStream();getinputStream();获得写和读的方法 其余的操作就和IO流的操作一样!!
      

  3.   

    我直接上代码吧!import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.HashMap;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;public class EchoServer {
    int ccid;
        public int getCcid() {
    return ccid;
    }
    public void setCcid(int ccid) {
    this.ccid = ccid;
    }
        //端口号
        private int port=3005;  
        //
        private ServerSocket serverSocket;  
        private ExecutorService executorService;
        private final int POOL_SIZE = 4;
        private HashMap<String, Socket> socketHashMap = new HashMap<String,Socket>();private HashMap<String,Ecc> eccHashMap = new HashMap<String,Ecc>();byte Packet_Head[]={0x4c,0x53};
        byte Packet_End[]={0x0d,0x0a};
        
        public EchoServer() throws IOException {     
        serverSocket = new ServerSocket(port);
        executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*POOL_SIZE);
        System.out.println("服务器启动");  
        }
        
        public void service() {    
            while (true) {      
                Socket socket=null;      
                try {        
                    socket = serverSocket.accept();      //接收客户连接  
                    //socket.setSoTimeout(10000);         //10秒无数据传输,连接自动断掉
                    socket.setSoTimeout(100000); 
                    executorService.execute(new Handler(socket));   //创建一个工作线程  ,加入到线程池      
                }catch (IOException e) {         
                    e.printStackTrace();      
                    }    
            }  
        }
        
            
        class Handler implements Runnable{
            private Socket socket;
            private InputStream br;
            private OutputStream pw;
            private byte reciver_buffer []=new byte [2048]; 
            private int recive_length;
            boolean login_succed = false;
    //        int ccid;
            
            public Handler(Socket socket){
                this.socket = socket;
            }
            
            
            public int indexOf(byte data[],int length_a,byte b[],int length_b){
                int i,j;
                    for(i=0;i<=(length_a-length_b);i++){
                            boolean isValid=true;
                            for(j=0;j<length_b;j++){
                                if(data[i+j]!=b[j]){
                                    isValid=false;
                                    break;
                                }
                            }
                            if(isValid){
                                    return i;
                            }
                    }
            return -1;        }
            public void run(){
                Socket sendSocket =null;
                
                Ecc ecc = new Ecc(socket);
                try{
                    System.out.println("New connection accepted"+
                            socket.getInetAddress()+":"+socket.getPort());
                    br = socket.getInputStream();
                    pw = socket.getOutputStream();
                    while(true){
                   recive_length=ecc.read(reciver_buffer);
                       if(recive_length!=-1){
                         int index_head=indexOf(reciver_buffer,reciver_buffer.length,Packet_Head,Packet_Head.length);  
                         System.out.println("packet_head index is:"+index_head);
                         if(index_head==-1) continue;
                         int index_end=indexOf(reciver_buffer,reciver_buffer.length,Packet_End,Packet_End.length);  
                         System.out.println("packet_end index is:"+index_end);
                         if(index_end==-1) continue;
                         int recive_sum = 0xff & reciver_buffer[index_end-1];
                         int check_sum=0;
                         for (int i = 2; i < recive_length - 3; i++)
                         {
                             check_sum+=0xff & reciver_buffer[i];
                         }
                         check_sum = check_sum & 0xff;
                         System.out.println("recive_sum is : "+ Integer.toHexString(recive_sum));
                         System.out.println("check_sum is : "+ Integer.toHexString(check_sum));
                         if((byte)recive_sum!=(byte)check_sum) continue;
                         System.out.println("data packet is valid!");
                         int packet_cmd = 0xff & reciver_buffer[3];
                         int packet_cmd_reserved =  0xff & reciver_buffer[4];
                         int recive_valid_length = ((0xff & reciver_buffer[7])<<8)+ (0xff & reciver_buffer[6]);
                         int valid_data_length = 0;
                         byte sum=0;
                         
                         switch (packet_cmd) {
                                            case 0x7e:
                                                            ccid = 0xff & reciver_buffer[5];
                                                            System.out.println("ccid is : "+ccid);
                                                            if (ccid==0x00) {
                                                                //控制客户端登陆
                                                                if(login_succed==false){
                                                                    //发登陆成功回应 
                                                                    valid_data_length = 0x06;
                                                                    byte send_longin_ack [] =  new byte[]{(byte) 0x4c,0x53,(byte)0x00,0x3f,0x00,(byte)ccid,(byte)valid_data_length,(byte)(valid_data_length>>8),
                                                                    0x00,0x00,0x00,0x00,0x00,0x00,sum,0x0d,0x0a};
                                                                    for(int i=0;i<send_longin_ack.length-3;i++)
                                                                        sum+=0xff & send_longin_ack[i];
                                                                    send_longin_ack[send_longin_ack.length-3]=(byte)sum;
                                                                    ecc.write(send_longin_ack);
                                                                    eccHashMap.put(""+ccid+"", ecc);
                                                                    
                                                                    login_succed = true;
                                                                    socket.setSoTimeout(0);
                                                                    System.out.println("ecc id:"+ccid+" longin succeed!");
                                                               }
                                                            }
                                                            else {
                                                                //ecc登陆
                                                                
                                                                   if(login_succed==false){
                                                                        //发登陆成功回应 
                                                                       //登陆成功,修改数据库状态 ccid
                                                                        valid_data_length = 0x06;
                                                                        byte send_longin_ack [] =  new byte[]{(byte)0x4c,0x53,(byte)0x00,0x3f,0x00,(byte)ccid,(byte)valid_data_length,(byte)(valid_data_length>>8),
                                                                                0x00,0x00,0x00,0x00,0x00,0x00,sum,0x0d,0x0a};
                                                                       for(int i=0;i<send_longin_ack.length-3;i++)
                                                                            sum+=0xff & send_longin_ack[i];
                                                                        send_longin_ack[send_longin_ack.length-3]=(byte)sum;
                                                                        ecc.write(send_longin_ack);       
                                                                        login_succed = true;
                                                                        System.out.println("ecc id:"+ccid+" longin succeed!");
    //                                                                    ccidHashSet.add(Integer.toHexString(ccid));
                                                                        socketHashMap.put(Integer.toHexString(ccid), socket);
                                                                   }
                                                            }
                                                
                                                            break;
                                            case 0x7b:
                                                            //心跳包 
                                                            //发心跳回应 
                                                            if(login_succed==true){
                                                                 valid_data_length = 0x00;                                                         byte send_heart_ack [] =  new byte[]{(byte) 0x4c,0x53,(byte)0x00,0x3e,0x00,(byte)ccid,(byte)valid_data_length,(byte)(valid_data_length>>8),
                                                                         sum,0x0d,0x0a};
                                                                 for(int i=0;i<send_heart_ack.length-3;i++)
                                                                        sum+=0xff & send_heart_ack[i];
                                                                 send_heart_ack[send_heart_ack.length-3]=(byte)sum;
                                                                 ecc.write(send_heart_ack);    
                                                            }
      

  4.   

                                                           break;
                                            case 0x20:
                                                            //查询数据回应 ,处理并存入数据库
                                                            if (login_succed==true) {
                                                                switch (packet_cmd_reserved) {
                                                                case 0x00://正常响应
                                                                            System.out.println("recive_valid_length is "+ recive_valid_length);
                                                                             byte send_meter [] = new byte [recive_valid_length];
                                                                             for (int i = 0; i < send_meter.length; i++) {
                                                                                send_meter[i] = reciver_buffer[i+8];
                                                                            }
                                                                             boolean crc_check = ModbusCrc16.checkBuf(send_meter);
                                                                             System.out.println("crc check is "+crc_check);
                                                                             if (crc_check) {
                                                                                MeterDatas meter = new MeterDatas(send_meter, ccid);
                                                                                if (meter.MeterUpdate()) {
                                                                                    //存到数据库或者直接传给需要客户端
                                                                                    System.out.println("DIO is :"+(0xff & meter.DIO));
                                                                                    System.out.println("Ua is :"+meter.Ua);
                                                                                    System.out.println("Ub is :"+meter.Ub);
                                                                                    System.out.println("Uc is :"+meter.Uc);
                                                                                    System.out.println("HZ is :"+meter.Hz);
                                                                                }
                                                                                else {
                                                                                    System.out.println("meter datas parse error!");
                                                                                }
                                                                            }
                                                                    break;
                                                                case 0x01://异常响应
                                                                                System.out.println("read meter error!");
                                                                    break;
                                                                default:
                                                                    break;
                                                                }
                                                            }
                                            
                                                break;              
                                            case 0xd0:
                                                            String eccidString = Integer.toString(((0xff & reciver_buffer[8])<<8)+(0xff & reciver_buffer[9])); 
                                                            System.out.println("eccid is "+ eccidString);
                                                            sendSocket=socketHashMap.get(eccidString);
                                                            if (sendSocket!=null) {
                                                                OutputStream sop = sendSocket.getOutputStream();
                                                                System.out.println("sendSocket is exsitl!");
                                                                valid_data_length = 0x0b;
                                                                byte sum1=0;
                                                                byte meterAddr =(byte) (0xff & reciver_buffer[10]);
                                                                byte meterCmd = (byte)0x10;
                                                                int regStartAddr =0x21;
                                                                int regCount = 0x01;
                                                                int crcValue=0x00;
                                                                int eccid =Integer.parseInt(eccidString, 16);
                                                                byte toggleButton=0;
                                                                if ((0xff & reciver_buffer[11])==0x01) {
                                                                    toggleButton =(byte)0xf0;
                                                                }
                                                                byte send_meter [] = new byte []{meterAddr,meterCmd,(byte)(regStartAddr>>8),(byte)regStartAddr,(byte)(regCount>>8),(byte)regCount,0x02,toggleButton,0x00};
                                                                ModbusCrc16 modbusCrc16 = new ModbusCrc16();
                                                                modbusCrc16.update(send_meter, send_meter.length);
                                                                crcValue=modbusCrc16.value;
                                                                byte send_control [] =  new byte[]{(byte) 0x4c,0x53,(byte)0xdf,0x00,(byte)(eccid>>8),(byte)eccid,(byte)valid_data_length,(byte)(valid_data_length>>8),
                                                                meterAddr,meterCmd,(byte)(regStartAddr>>8),(byte)regStartAddr,(byte)(regCount>>8),(byte)regCount,0x02,toggleButton,0x00,(byte)crcValue,(byte)(crcValue>>8),sum1,0x0d,0x0a};
                                                                for(int i=0;i<send_control.length-3;i++)
                                                                        sum1+=0xff & send_control[i];
                                                                send_control[send_control.length-3]=(byte)sum1;
                                                                sop.write(send_control, 0, send_control.length);
                                                                System.out.println("send control meter cmd finished!");
                                                                sendSocket = null;
                                                            }
                                                            else {
                                                                System.out.println("sendSocket is null!");
                                                            }
                                                            
                                                break;
                                            default:
                                                break;
                        }
                        }
                        else
                            break;
                    }
                }catch (Exception e) {
                            e.printStackTrace();
                }finally{
                    try {
                        if(socket != null) {
                            login_succed=false;
    //                        ccidHashSet.remove(Integer.toHexString(ccid));
                            socketHashMap.remove(Integer.toHexString(ccid));
                            socket.shutdownInput();
                            socket.shutdownOutput();
                            br.close();
                            pw.close();
                            socket.close();
                              //断开连接,修改数据库状态 ccid
                            }
                         System.out.println(socket.getInetAddress()+":"+socket.getPort()+" is closed.");
                        } catch (Exception e2) {
                        e2.printStackTrace();
                    }
                    
                }
            }
            
            
        }
        public static void main(String[] args)throws IOException {
            // TODO Auto-generated method stub
            
            new EchoServer().service();
            
             
        }
        
        
    }以上是第一个类
    package com.linksprite.devices;import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.Socket;public class Ecc {

    private Socket m_sock;
    private InputStream m_inputStream;
    private OutputStream m_outputStream;

    public Ecc(Socket sock)
    {
    m_sock = sock;

    try {
    m_inputStream = m_sock.getInputStream();
    m_outputStream = m_sock.getOutputStream();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }

    public int read(byte[] buffer)
    {
    try {
    return m_inputStream.read(buffer);
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    return 0;
    }
    }

    public void write(byte[] buffer)
    {
    try{
    m_outputStream.write(buffer);
    }
    catch (IOException e)
    {
    e.printStackTrace();
    }
    }
    }
    这是第二个类
    我没明白   如何从EchoServer里面获得CCID  然后再根据需求发送给客户端指定的数据包 
    我没明白这个怎么写。
    但是  现在的一个问题是,我要获得的CCID   得是从之前已经连接上来的客户端的线程获取。求解 应该怎么做?
      

  5.   

    楼主C语言出身的 ?
    没有根据交互过程进行类的封装啊。这个协议本身我都没弄明白,更别说CCID了。
    至于楼主的问题,根据经验,当客户端连接到服务端之后,客户端发送特定的数据包给服务端,里面含有CCID,
    服务端接收该数据包后,解析数据包,得到CCID,就OK了。
      

  6.   

    我又定义了一个private HashMap<String,Ecc> eccHashMap = new HashMap<String,Ecc>();
    然后写了一个    public void sendMessage(byte ccid){
         Ecc ecc=eccHashMap.get(ccid);
         byte sendOpenLight[] = new byte[]{(byte)0x4c,0x53,ccid};
         ecc.write(sendOpenLight);
        }
    如果我现在想测试一下这个代码,用一个软件模拟客户端发送数据包上来,然后用HashMap存入连接进来的客户端,然后我用那个sendMessage的方法获得客户端登陆连接进来的ccid,并且写入指定的数据包,在上面的这个方法中,我随意定义了一个数据包。作为测试···  那么我写测试类  应该如何写呢?