列位大哥大姐,小弟的一个程序,C/S模式,客户端和服务器通过socket 传递对象,这个程序使用了很久了
都没有出现问题,但是最近发生了一个问题,服务器部署在局域网中,客户端在外网,二者通过路由器,连接是正常的
可以ping通,客户端也可以正常的登陆服务器,但是在进行数据交互的时候,发现服务器端和客户端均会出现异常,
数据交互采用发送对象的方式,在局域网使用的时候,从来没有发生过异常,帮我找找是什么原因吧?谢谢!
出现异常的时候:
服务器端打印:
 Socket closed
  - java.net.SocketOutputStream.socketWrite(Unknown Source)
- java.net.SocketOutputStream.write(Unknown Source)
 - java.io.ObjectOutputStream$BlockDataOutputStream.drain(Unknown Source)
 - java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(Unknown Source)
  - java.io.ObjectOutputStream.writeNonProxyDesc(Unknown Source)
  - java.io.ObjectOutputStream.writeClassDesc(Unknown Source)
  - java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
  - java.io.ObjectOutputStream.writeObject0(Unknown Source)
  - java.io.ObjectOutputStream.writeFatalException(Unknown Source)
 - java.io.ObjectOutputStream.writeUnshared(Unknown Source)
 - --------------------ERROR END-------------------------
客户端打印:
 Socket closed
 - java.net.SocketInputStream.socketRead0(Native Method)
  - java.net.SocketInputStream.read(SocketInputStream.java:129)
 - java.net.SocketInputStream.read(SocketInputStream.java:182)
 - java.io.ObjectInputStream$PeekInputStream.read(ObjectInputStream.java:2256)
  - java.io.ObjectInputStream$BlockDataInputStream.read(ObjectInputStream.java:2573)
  - java.io.ObjectInputStream$BlockDataInputStream.readByte(ObjectInputStream.java:2718)
 - java.io.ObjectInputStream.readByte(ObjectInputStream.java:895)
- java.io.ObjectStreamClass.readNonProxy(ObjectStreamClass.java:648)
  - java.io.ObjectInputStream.readClassDescriptor(ObjectInputStream.java:809)
 - java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1565)
  - java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1496)
 - java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1732)
 - java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
  - java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1945)
 - java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1869)
 - java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
  - java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
  - java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1945)
  - java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1869)
 - java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
 - java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
 - java.io.ObjectInputStream.readUnshared(ObjectInputStream.java:441)

解决方案 »

  1.   

     - java.io.ObjectOutputStream.writeNonProxyDesc(Unknown Source) 应该是路由器代理的问题你设定的是tcp 连接吧,需要有两个真实IP,目前你的服务器是内网IP哦你要设置PROXY
      

  2.   


    谢谢大侠,我的服务器是内网的IP,客户端是外网的,请问如何设置PROXY呢?谢谢
      

  3.   

    你是用tcp长连接么,一般tcp长连接不会有这样的问题...?还是服务端在客户端登录时一直保持连接还是登录完成功后就释放掉,服务端要写数据时又请求服务端连接?
      

  4.   

    答:服务器部署在局域网中,我想服务器的IP一般是内网IP(即:人们所说的私用IP).
    客户端在外网,客户端IP一般是公网IP.
    要向处于内网的私用IP的服务器发起TCP连接,你应该在你的路由器中设反向端口映射(即:将内网服务器的PORT,由路由器反向映射过来),这样,你的客户端的TCP其实是与路由器的IP及特定PORT进行连接的,由于设置过PORT的反向映射,路由器会自动将TCP数据再反向传送给内网的服务器.给客户机的感觉好像是与内网的服务器直接TCP连接一样.
    因此:做一个PORT映射.
    或者:若你有一个SOCKV5的代理(注:不是HTTP代码或FTP代理,必须是SOCKV4或V5代码),则可用下列代码进行设置:(在网络代码之前,首先设置)
    Properties p=System.getProperties();
    p.setProperty("socksProxyHost","你的代理的IP");
    p.setProperty("socksProxyPort","你的代理的PORT");//默认是:1080
      

  5.   

    引用楼主 hwbxc 的帖子:
    列位大哥大姐,小弟的一个程序,C/S模式,客户端和服务器通过socket 传递对象,这个程序使用了很久了 
    都没有出现问题,但是最近发生了一个问题,服务器部署在局域网中,客户端在外网,二者通过路由器,连接是正常的 
    可以ping通,客户端也可以正常的登陆服务器,但是在进行数据交互的时候,发现服务器端和客户端均会出现异常, 
    数据交互采用发送对象的方式,在局域网使用的时候,从来没有发生过异常,帮我找找是什么原因吧?谢… 
     
    答:服务器部署在局域网中,我想服务器的IP一般是内网IP(即:人们所说的私用IP). 
    客户端在外网,客户端IP一般是公网IP. 
    要向处于内网的私用IP的服务器发起TCP连接,你应该在你的路由器中设反向端口映射(即:将内网服务器的PORT,由路由器反向映射过来),这样,你的客户端的TCP其实是与路由器的IP及特定PORT进行连接的,由于设置过PORT的反向映射,路由器会自动将TCP数据再反向传送给内网的服务器.给客户机的感觉好像是与内网的服务器直接TCP连接一样. 
    因此:做一个PORT映射. 
    或者:若你有一个SOCKV5的代理(注:不是HTTP代码或FTP代理,必须是SOCKV4或V5代码),则可用下列代码进行设置:(在网络代码之前,首先设置) 
    Properties p=System.getProperties(); 
    p.setProperty("socksProxyHost","你的代理的IP"); 
    p.setProperty("socksProxyPort","你的代理的PORT");//默认是:1080 
    ===============================================================================================谢谢你的回复:我还是有一些不明白的地方:现在我们的服务器部署的机器的IP是:10.99.129.2  监听端口:7777从客户端执行tracert 10.99.129.2 得到:
    Tracing route to 10.99.129.2 over a maximum of 30 hops1  2ms  2ms   2ms    10.99.66.254
    2  12ms 10ms  10ms   10.99.254.18
    3  5ms  6ms    6ms   10.99.129.2Trace complete根据我们的组网情况,客户端所在机器到服务器经过了两次路由器的转发。在操作的时候,客户端登陆服务器,10.99.129.2 监听端口:7777可以登陆,这就说明服务器端接受了这个客户端的连接。按照你的说法,如果没有做端口映射,那服务器应该不能接受客户端的连接吧〉?在客户端连接之后,服务器会向客户端发对象,这个时候双方都出现了我主贴中出现的异常。请赐教!
      

  6.   

    可以登陆,这就说明服务器端接受了这个客户端的连接。 按照你的说法,如果没有做端口映射,那服务器应该不能接受客户端的连接吧〉? 
    答:若你确认:客户机从公网IP已经确实通过TCP登陆到内网的私用IP的服务器上,说明你的网络在路由器上已经对你的内网IP的服务顺做了配置(如:PORT的映射--映射到指定内网IP上的指定PORT上或者:代理),若这个条件真正成立:则:通过这个TCP的连接,就可以传任何数据(只要数据包不是被防火墙拦截).
      

  7.   


    ================================================================客户端确实可以登陆服务器,这个我是可以确认的,组网的情况我只能tracert一下,因为服务器已经被他人使用具体的组网情况不能确认,但是客户端到服务器可以ping通,也可以登陆,就是发数据的时候有问题。
      

  8.   

    最好做个断点调试下,看看服务器、客户端到底接收到什么地址
    然后单步,看看哪里出了问题。如果你嫌程序太大,可以自己组个模块出来调试,很容易
    我们跟着猜也很难的Proxy 原理就像 云上飞翔说的没错
    剥离内网IP,转换成公网IP+端口