client是c++,server是java.客户端和server端保持长链接。
线程Child,启动socket服务
PrintStream ps = null;
 private Socket client;
 public void run(){       
            try{  
     ThreadCache.getIns().getHtMap().put(ip, client);//将当前连接信息寸到自己定义的一个map里,ip做为key
  while(true){
                  byte[] length = new byte[4]; //这里是因为定义的报文格式前面4位是整个报文的长度 0123<root><content>.........</content></root>这样
                dis.read(length);    //下面是业务处理
}
上面一段都没有问题,客户端和server端得互相通信都正常。现在有个需求,从网页向server传个命令,再由server转发到client.
servlet b的内容
Map tmap=ThreadCache.getIns().getHtMap();
  
    String key = getFriendIpAddress();//自定义方法,获取客户端ip
    Socket client = tmap.get(key ); 
    OutputStream os= client.getOutputStream();
    ps=new PrintStream(os,true,"utf-8");
    ps.write(msg.getBytes("utf-8"));//出错处
  

网页发送命令后,到server端获取连接为止都没有问题,到发送的时候就会报错
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:168)
at java.io.DataInputStream.read(DataInputStream.java:80)
at com.socket.Child.run(Child.java:48) //ChildTh就是保持长链接的那个线程
at java.lang.Thread.run(Thread.java:595)
网上查了下,关于杀软的原因排除,因为我是本机测试,防火墙和杀软我全部关掉的。不知道是不是由阻塞引起的,但是我获取的是client的输出流,并非输入流,应该没有数据等待的,哪位朋友有做过这快的指点一下。不盛感激。。

解决方案 »

  1.   

    String key = getFriendIpAddress();//自定义方法,获取客户端ip
    Socket client = tmap.get(key );  
    OutputStream os= client.getOutputStream();
    ps=new PrintStream(os,true,"utf-8");
    ps.write(msg.getBytes("utf-8"));//出错处
    试验一下,直接向某个ip发msg会报错么?
      

  2.   

    ps.write(msg.getBytes("utf-8"));//出错处
    这么一句话不能错啊。而且报的是Connection reset 应该连接都没有获取到
      

  3.   

    客户端不可能关闭的,一直保持在那里的,不到超时是不会断的,因为不加web功能的话,server和client之间的通讯是不存在任何问题的。
      

  4.   

    是阻塞引起的,采用nio非阻塞模式可以解决你这个问题的。也是一样的道理的,建立连接后,把这个连接存到缓存里,因为它不是采用流阻塞机制来等待数据,而是采用通道注册来接收数据的,所以不会引起阻塞。查一下吧,网上代码比较简单,大多是对单客户端机制的,如果你的阻塞方式解决了多客户机的问题,那么可以解决的,把服务端初始化放在循环外面就行了。你服务端主动推送的时候,不需要再去注册通道,直接用连接write就可以了。实在不行,到时候给你代码。