当前位置: 代码迷 >> J2SE >> 棘手的Socket有关问题,涉及到多线程。请大家帮忙
  详细解决方案

棘手的Socket有关问题,涉及到多线程。请大家帮忙

热度:101   发布时间:2016-04-24 13:20:02.0
棘手的Socket问题,涉及到多线程。请大家帮忙!
为了把问题说明清楚,把我写的代码贴出来(共三部分),请大家为我解答:

一个是Socket的服务端(用Java编写的),另一个是Socket的客户端(这个Socket客户端C++写的)。Socket的服务端可以向Socket的客户端发送信令,这个大家都知道,但现在Socket的服务端必须要抛出一个多线程便于一直接收Socket客户端发过来的信令,不然若客户端有什么请求,我就不知道了.  
注:客户端必须先向服务端链接,这样服务端才得到一个链接(Socket).
下面详细说明一下:
  服务器先起来,然后客户端向服务器端建立一个连接,服务器端收到连接后,用一个全局变量保存起来; 
  在这里保存起来有两个目的:1.让服务端保持这个链接,不需要以后重新再链接,2.可以在其它方法里(比如C部分)利用这个保存的Socket向客户端发信。 
各个部分的含义: 
  A部分,服务器端收到客户端的连接,并将这个链接(socket)保存起来,注意,服务器端收到连接后并不是立即给客户端发送信令,具体向客户端发信的是通过C部分实现的;然后new SocketServerThread(socket).start(),便于可以一直(随时)接收客户端的信令。 
  B部分,接收客户端的信令。因为要可以随时接收不同客户端的信令(业务要求),所以要用到多线程。当通过C部分向客户端发送信令后(送信的内容是xml体,里面包含sessionid等其它数据),那么只能(因为要随时接收不同客户端的信令,所以用一个while循环)通过这个多线程接收了。先发送,再等待返回。那当多线程收到客户端信令的返回时,怎么通知C部分(已经收到返回了)呢?所以就在多线程里用一个全局Map把这个结果保存起来,便于C部分可以通过轮询这个变量,已得知客户端已返回。那怎么确定信息是C的哪次发信返回的结果呢?就是通过sessionid的值来确定的(下面有说明),即我每次在送信前记住这个sessionid,在收信时就找对应的结果(结果也是一个xml体)。每次送信的sessionid都不相同。这是一个瓶颈,尤其在多线程里,这正是我提问题的原因所在。 
  C部分,利用全局Map保存的socket向客户端发送信令;轮询这个变量,通过sessionid查找对应的结果,看多线程(B部分)是否收到客户端信令的返回。

这是一个会议系统,只要创建会议(是通过用户在页面点击来调用C部分的方法来发起通信的),都会送信。 
这是每次送信的内容,是一个xml体,即: 
Java code
<iabi> <cmd   id= "3000 "   sessionid= "1412412341 "> <confid> 88888888 </confid> </cmd> </iabi> 


   
A部分:
Java code
public class SocketServer extends Thread {    private Logger log= Logger.getLogger(SocketServer.class.getName());            private ServerSocket serverSocket;    private int listenPort =8188;    public SocketServer(int listenPort) {        this.listenPort = listenPort;    }    public static Map socketMap=new HashMap();//保存socket的HashMap    public static Map resultMap=new HashMap();//保存发出通信的的返回结果Map    private Socket socket;    private boolean isLoop= false;    public void run(){        isLoop=true;                try {            serverSocket= new ServerSocket(listenPort);            log.info("Starting listen......");            String ccsIp="";            CcsInfo ccsInfo=null;            while(isLoop){                                socket = serverSocket.accept();                                            log.info("Listening->RemoteSocketAddress:"+socket.getRemoteSocketAddress()+" InetAddress:"+socket.getInetAddress());                ccsIp=socket.getRemoteSocketAddress().toString().trim();                ccsIp=ccsIp.substring(1,ccsIp.indexOf(":"));                log.info("RemoteSocketIp:"+ccsIp);                        socketMap.put(ccsIp,socket);                    log.info("Having listen the IP:" +ccsIp+" The ccsID:"+ccsInfo.getCcsId());                        new SocketServerThread(socket).start();            }        } catch (Exception e) {            isLoop = false;            log.error("    "+e);        }    }        }



B部分:
Java code
public class SocketServerThread extends Thread {        private Logger log= Logger.getLogger(SocketServerThread.class.getName());        private Socket socket;    private int result;    private boolean isLoop;    ByteArrayOutputStream buf = new ByteArrayOutputStream();    public SocketServerThread(Socket s){        this.socket = s;    }    public void run(){        isLoop=true;        result=0;        InputStream in=null;        try {            in =new BufferedInputStream(socket.getInputStream());        } catch (IOException e){            log.error("The CCS "+socket.getRemoteSocketAddress()+" is unusual:"+e);        }        int readLen=1024;        int count=0;        byte[] readBuf=new byte[readLen];        while(true&&isLoop){            count=0;            try{                do{                    count=in.read(readBuf);                    if(count==-1){                        isLoop=false;                        throw new IOException("The receive data length is not right");                                  }                                                            buf.write(readBuf,0,count);                }while (count==readLen);                log.info("Receive:"+new String(buf.toByteArray()));            }catch(IOException ex){                log.error("The CCS "+socket.getRemoteSocketAddress()+" correspondence is unusual:"+ex);            }             //收到的结果是一个xml体,然后解析出sessionid和通信的结果result                          SocketServer.resultMap.put(sessionid,result);//保存返回结果               }      }}
  相关解决方案