通信常见错误
当服务器端口号和客户端的端口号不一致的时候,将会抛出ConnectException异常,此异常“试图将套接字连接到远程地址和端口时发生错误的情况下,抛出此异常。这些错误通常发生在拒绝远程连接时(例如,没有任何进程在远程地址/端口上进行侦听)”。

?
?
2、循环
在服务器端等待客户端连接(ss.accept())的时候,需要一个while(true),否则服务器只能连接一个客户端,达不到客户端的群发消息和客户端与客户端之间的独聊的目的。
在界面显示消息的时候,因为需要不仅把当前接收到的消息显示出来,还需要将以前接收过来的历史消息也要显示出来,所以就需要把消息添加到一个String数组中,for循环显示出来。
?
3、内存泄露:
首先要认识到内存泄漏并非指内存在物理上的消失,而是程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。Java的内存的泄漏是指程序对象在引用过申请到内存后,再也没有被使用过,而此时java的垃圾回收机制GC并不能识别这一对象的内存是否该要回收,致使内存的浪费。当然,只要是问题,就会有解答,产生这一错误无非包含两点:对象被引用,且对象是无用的。根据这一线索,就可以很好的发现并处理内存的泄漏。
?
4、try-catch和throws:
异常的处理在通信中很是纠结。在通信中,有IO流的异常,也有UnknownHostException。

?
至于是要使用try-catch还是throws,就又要回到java的异常机制那一节了,老实说我现在还不懂怎么去解决异常,try-catch还是throws纯粹看着心情,但偏爱try-catch,显得程序员本人有责任心点。
?
5、线程控制:
在通信过程中,多线程是必不可少的,线程的处理十分重要。

?
在服务器和客户端接受消息的时候,因为接收消息是在程序运行过程中无时无刻不在进行的,所以需要一个死循环,而死循环后,程序就会卡在循环中执行,如若不启用多线程,程序中的其它方法就会执行不到。而此刻所说的多线程处理也非真正意义上的多线程处理,这里只是一种程序方法的优先级处理,当数据到达cpu的时候,都是单个的过去的,当然现在的双核或多核处理器就可以达到真正的多线程处理了。
?
6、流的关闭:
众所周知,当IO流用完后,需要close掉,可在通信中我遇到了一个矛盾的问题。因为客户端或服务器端接受消息是每时每刻的,而当我把IO流在我认为的地方关闭后,接收消息的inputStream就会断开,程序就会报错
?,所以,只有在程序关闭的时候才能close掉IO流,可程序都已经关闭了,还关心什么IO流的开闭呢。输出流也一样,当按下界面上的send按钮的时候,触发监听器,将sendArea里的消息内容写到outputStream里,写完后,该要关闭IO输出流,可下一次按下send按钮的时候,就又得新建一条IO通道,联通服务器,这才能输出消息,在这一开一关间,是否有点不必要。所以我暂时认为在通信中,IO流不要关闭。虽然知道自己这一想法大多是错误的,可现在力不足当安于现实,仍在继续探索中。
?
7、read和readfully:
read和readfully其实都是调用的inputStream中的read()方法。read是读取一个length的数组,当length大于输入流的长度的时候,read就提前返回;而readfully是读取一个固定长度的数组,如果长度小于输入流的长度,readfully读取指定的长度后返回,如果声明的长度大于输入流的长度的时候,readfully会阻塞等待,直到超时抛出EOFException异常。
?
read
public int read()
???????? throws IOException
读取单个字符。
覆盖:
类 Reader 中的 read
返回:
读取的字符,如果已到达流的末尾,则返回 -1
抛出:
IOException - 如果发生 I/O 错误
read
public int read(char[]?cbuf,
??????????????? int?offset,
??????????????? int?length)
???????? throws IOException
将字符读入数组中的某一部分。
指定者:
类 Reader 中的 read
参数:
cbuf - 目标缓冲区
offset - 以其处开始存储字符的偏移量
length - 要读取的最大字符数
返回:
读取的字符数,如果已到达流的末尾,则返回 -1
抛出:
IOException - 如果发生 I/O 错误
?
readFully
void readFully(byte[]?b)
?????????????? throws IOException
从输入流中读取一些字节,并将它们存储到缓冲区数组 b 中。读取的字节数等于 b 的长度。
在出现以下条件之一前,此方法将阻塞:
如果 b 为 null,则抛出 NullPointerException。如果 b.length 为零,则不读取字节。否则,将读取的第一个字节存储到元素 b[0] 中,下一个字节存储到 b[1] 中,依此类推。如果此方法抛出异常,则可能是因为已经用输入流中的数据更新了 b 的某些(但非全部)字节。
参数:
b - 存储读取数据的缓冲区。
抛出:
EOFException - 如果此流在读取所有字节之前到达末尾。
IOException - 如果发生 I/O 错误。
readFully
void readFully(byte[]?b,
?????????????? int?off,
?????????????? int?len)
?????????????? throws IOException
从输入流中读取 len 个字节。
在出现以下条件之一以前,此方法将阻塞:
如果 b 为 null,则抛出 NullPointerException。如果 off 为负,或 len 为负,抑或 off+len 大于数组 b 的长度,则抛出 IndexOutOfBoundsException。如果 len 为零,则不读取字节。否则,将读取的第一个字节存储到元素 b[off] 中,下一个字节存储到 b[off+1] 中,依此类推。读取的字节数至多等于 b[0]。
参数:
b - 存储读取数据的缓冲区。
off - 指定数据中的偏移量的 int。
len - 指定读取的字节数的 int。
抛出:
EOFException - 如果此流在读取所有字节之前到达末尾。
IOException - 如果发生 I/O 错误。
8、try-while:
这是一个很容易出现而又很容易解决的错误。
?
在编写通信的过程中,容易出现的错误不仅仅是上述的8点,还有方法的声明,乱码,违反协议,协议的缺陷等等,不管是我枚举到的还是暂时没有发现到的,由于一些错误并没有亲身经历,不能够很好的总结,但继续努力中。