论坛首页 Java企业应用论坛

网络通信常见错误(问题)个人总结

浏览 4468 次
精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2010-07-28  

 

最近在学习java网络通信方面的知识,学习的过程就是一个不断总结的过程,通信整个过程需要注意的内容很多,下面就在网络通信中常见的错误或者问题进行一个短暂的总结:

 

 1.ip port已被占用或错误

 

 学习通信的在初期通常都犯过这个错误,一台电脑的端口值为1到65535之间,另外对于要连接的服务器本身ip地址可以通过ipconfig来获得,端口被占用错误出现的较频繁,当一个服务器启动时,端口已经被占用,在再次启动时需要将以前的关闭。


2.循环导致错误 (慎用while true)

 在通信中有许多过程都是阻塞的,特别是传输过程中的流的写入和读取都需要循环来完成,有时候循环位置不当也可以出错。下面给出一段代码示例:

try{
		ServerSocket myser=new ServerSocket(port);
		System.out.println("创建服务器成功");
		Socket client=myser.accept();
		while(true){
		SerThread ser=new SerThread(client);
		ser.start();
		}
		}catch(Exception ex){
			ex.printStackTrace();
		}

  在这段代码中,当连接到一个socket对象时就需要将其放到一个线程中去处理,这段代码错误在于while“达到”的目的是不断的用这个socket建 SerThread,久而久之就会最终导致服务器内存溢出,报错。正确的代码应该是 :

try{
		ServerSocket myser=new ServerSocket(port);
		 System.out.println("创建服务器成功");
		while(true){
		Socket client=myser.accept();
		SerThread ser=new SerThread(client);
		ser.start();
		}
		}catch(Exception ex){
			ex.printStackTrace();
		}

 
3.服务器客户端协议不一致

 

  网络通信中各种流的传输都需要协议来约束,没有协议就没有网络通信就没有互联网,因此在通信过程自定义协议过程中一定要保证服务器和客户端都严格按照规定的协议写入和读取流,也许仅仅是一个byte没有读取到都会导致整个流的读取错误,最后会报错。


4.read和readfully

 

 两种方法都可以返回一个byte[],查看java API文档可以看到输入流read方法的说明:

写道
从包含的输入流中读取一定数量的字节,并将它们存储到缓冲区数组 b 中。以整数形式返回实际读取的字节数。在输入数据可用、检测到文件末尾 (end of file) 或抛出异常之前,此方法将一直阻塞。
如果 b 为 null,则抛出 NullPointerException。如果 b 的长度为 0,则不读取字节并返回 0;否则,尝试读取至少一个字节。如果因为流位于文件末尾而没有字节可用,则返回值 -1;否则至少读取一个字节并将其存储到 b 中。

将读取的第一个字节存储到元素 b[0] 中,将下一个字节存储到 b[1] 中,依此类推。读取的字节数至多等于 b 的长度。设 k 为实际读取的字节数;这些字节将存储在从 b[0] 到 b[k-1] 的元素中,b[k] 到 b[b.length-1] 的元素不受影响。

read(b) 方法与以下方法的效果相同:

read(b, 0, b.length)

  read当读取的数组满或者到文件末尾时会返回,因此返回的不一定是一个满的数组,下面看下readfully的API说明:

写道
从输入流中读取一些字节,并将它们存储在缓冲区数组 b 中。读取的字节数等于 b 的长度。
在出现以下条件之一以前,此方法将一直阻塞:


输入数据的 b.length 个字节是可用的,在这种情况下,正常返回。
检测到文件末尾,在这种情况下,抛出 EOFException。
发生 I/O 错误,在这种情况下,将抛出 IOException,而不是 EOFException。
如果 b 为 null,则抛出 NullPointerException。如果 b.length 为零,则不读取字节。否则,将读取的第一个字节存储到元素 b[0] 中,下一个字节存储到 b[1] 中,依此类推。如果此方法抛出异常,则可能是因为已经用输入流中的数据更新了 b 的某些(但非全部)字节。


   这个方法返回的一定是一个完整的数组,而且当读取到末尾但是数组还是未满时会抛出EOFException,这样两者的区别就很明显了。


5内存溢出

 

 内存溢出这个容易发现,只要细心就可以尽量避免,当然这个内存溢出肯能是由于流的读取或者其他问题造成的。给出最简单的示例:

                 int len=5686544;
                 byte[] by=new byte[len];

  一太电脑的内存有限,分配给一个程序的空间有限,超过这个限度就是溢出。


6EOFException

 

 在上面的readfully的说明有出现异常的情况。具体说明为:

写道
当输入过程中意外到达文件或流的末尾时,抛出此异常。

此异常主要被数据输入流用来表明到达流的末尾。注意,其他许多输入操作返回一个特殊值表示到达流的末尾,而不是抛出异常。

   当文件或者流已经结束,但是程序缺还在阻塞的读取数据就会出现这种异常。

 

7突然中断通信(正常的异常)

   之所以说这是一种正常的异常是因为这个异常并不是程序本身的错误,是程序员本身不能控制的,比如突然某一端掉线或者突然断电都会导致通信失败,抛出异常,我们在写程序过程中要考虑这种情况,及时在出现时print信息。


8.程序性能问题

    一段程序需要其运行的时间空间复杂度尽量的小,这样的程序才是可取的,这是每个程序员需要注意并且不断改善的。下面阐述一种最简单的,比如在一个循环中需要某个对象的方法,很多人都会把创建对象放到循环中去。这样每次都会创建一个对象,这样会不断的消耗内存,简单的处理就是将这个对象作为属性来处理。


9.try{}catch和throw

   try catch是在catch中直接对出现的错误进行处理,或者打印信息,或者调用另 外的程序,而throw就是将异常的处理方法交给调用这个方法的代码去处理,有点不负责的意味,两者主要是在使用场合上,合适的场合使用合适的处理方法。

 

  目前先写这么多吧,当然以前以后遇到的错误还会更多,这是一个不断的总结锻炼的过程,成为一个程序员就要在过程中不断的犯错,不断的提高,这样才能不断进步。

 最后送给自己,也送给所有看到这篇文章的读者:记住,你是最棒的!

 

 

 

   发表时间:2010-07-29   最后修改:2010-07-29

引用
最后送给自己,也送给所有看到这篇文章的读者:记住,你是最棒的!

那到底是你最棒,还是看过这篇文章的读者的我最棒?
还是并列最棒?还是最棒之一?
0 请登录后投票
   发表时间:2010-07-29  
2.很少有人会犯这样的错误,比较常见的死循环是在做读取的时候。另外楼主的代码应该用线程池。
3.“read当读取的数组满或者到文件末尾时会返回” 不一定,阻塞读只要读到至少一个字节就可能返回(如果此时出现网络传送延迟),这不一定是达到流的尾端。
8.有时候你必须在循环里创建对象,因为某些情况下,创建对象的代价要远远小于维护同步的成本。
9.throw有它的用处,尤其是你catch无法做任何有帮助性的处理。
0 请登录后投票
   发表时间:2010-07-30  
2.很少有人会犯这样的错误,比较常见的死循环是在做读取的时候。另外楼主的代码应该用线程池。

那个循环是在不断读取数据时使用的,是放到线程中的!我没有贴上去前面的!!
0 请登录后投票
   发表时间:2010-07-30  
congdepeng 写道

引用
最后送给自己,也送给所有看到这篇文章的读者:记住,你是最棒的!

那到底是你最棒,还是看过这篇文章的读者的我最棒?
还是并列最棒?还是最棒之一?


这句话只是给自己一种信心或者激励!自己目前刚开始学习java不久,希望自己不断进步,我希望java最后成为的找工作的敲门砖!当然你要是刻意的去追究谁是最棒的话就有点钻了!毕竟生活不是辩论场!
0 请登录后投票
   发表时间:2010-07-30  
3.“read当读取的数组满或者到文件末尾时会返回” 不一定,阻塞读只要读到至少一个字节就可能返回(如果此时出现网络传送延迟),这不一定是达到流的尾端。
8.有时候你必须在循环里创建对象,因为某些情况下,创建对象的代价要远远小于维护同步的成本。

总结中提到循环中创造对象的用意是为了提高程序的性能。不断的创造对象会不断的占用内存。如果在某种情况下如果这样更好,当然可以用!毕竟在大多数情况下要注意这个问题!

输入流的read方法与readfully的方法主要的区别就在read读出的数组未必是满的!可能是初学的缘故吧,有些东西还不是太懂,不过谢谢您的回复!我会再查下相关资料!!
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics