[音乐]
好,我们下面呢来看看呢,实现底层的网络通信。
那要实现底层网络通信呢,我们经常要用个socket类,或者 中文名呢叫套接字,这么翻译
或者我们不翻译呢就叫socket,这个socket呢它就是 表示客户和服务端相连的一种机制。
那这个类呢,我们在建立的时候要指明,比如说我们在客户端要指明呢
跟哪一个机器名或者ip地址的哪一个端口号相连
所以在构造这个socket的时候呢,要指定呢服务器的
ip地址,或者端口号,有了这个socket然后我们就可以用
流,就是stream呢,来进行输入和输出,那实际上就是通信了 这是客户端用socket类。
那么服务端呢,要用到serversocket 以及socket类,serversocket呢就是服务端的这个通信那个类,
它里面有一个accept方法来结束 客户的呼叫,来结束客户的连接,
那返回的又是一个socket对象,这个socket对象呢,它代表的是 客户,代表的是服务端
与客户端进行通信,所以呢我们也就是说 实现底层的通信的,主要就用这两个类,我们下面呢来看一下
客户端和服务端,它的基本的写法。
请看这里,这里呢有一个socket对象,我们跟服务端相连,
然后这个服务端呢,它要指明服务端的ip地址 和端口号。
那么端口号呢,实际上就是一个整数了,那我们一般说来呢
在访问网络的时候大家经常看见呢,如果我跟 这个服务端,www的服务端通信的时候,经常有一个
比如说8080,等等,类似的端口,那有了这个socket,我们就可以呢
getInputStream,就得到一个流。
那顺便解释一下,这里127.0.0.1实际上呢它不是一个
普通的ip地址,它就是指本机,就是当前这台机器,所以它指的本机ip地址。
我们刚才用getInputStream呢得到一个流,这个流呢 我们甚至可以把它包装成别的流,比如说是DataInputStream,
或者呢,其它的这个流,根据需要了,然后在这里面
就可以用它来read,来读取, 读取完了以后再关闭,所以这就是一个socket加一个流的过程。
那我们 再看看服务端,服务端呢,它有个serversocket
那它指明我服务的一个端口号也就是说刚才客户端 呢跟服务端连接这个端口号要一致,有一个端口号,然后呢
有这样一个socket以后,下面我们注意呢,一般 说来呢,服务端要跟多个客户端相连,所以呢
一般情况下它是一个循环,就是并且呢是一个无限的循环,也就是说服务器呢一直在服务。
while true,就是一个无限的循环,那它要做的事情就是accept
接受一个客户,它就等待客户的一个呼叫。
然后呢,等待完了以后呢 得到的也是一个socket,那么这个socket呢就跟客户进行通信
同样的,它也有流,这个流呢我们也可以把它封装成我们需要的
这种流,然后用write写信息,这个 写信息呢,实际上就是服务端写到客户端去了
总的说来呢,客户端跟服务端的通信呢就是用socket 那么,由于服务端呢经常就需要呢
处理多个客户,所以呢这个时候呢 我们用线程是最好的,有多个客户 进行通信。
我们下面再看看一个例子。
请看这个例子,我们这里有一个
服务端,然后呢有多个客户端 那服务端启动以后呢,它一直在这iii听,也就是它有个serversocket
这里,那我们的客户端呢 也要建立一个连接,所以也就是要建立那个socket
好,它连接以后呢,那服务端呢就能感知到了,服务端呢然后就 要跟它进行通信。
同样的,我们另一个客户端连接 了以后,那它也要跟它进行通信,所以这个呢,有多个任务呢,同时进行
所以我们这里呢,最好就是用线程来并发的进行处理,当然
服务端呢跟客户端呢可以进行信息的通信,我们这里呢简单地
输入一串信息,好,这个信息呢 发送到服务端以后,服务端呢它可以做各种处理
比如说,它把它广播到所有跟它当前相连的这个客户,这样的话就达到一个
就是,在一定要通过这个服务端的
中转,服务端再发到别的客户呢,就能达到这两个客户端之间呢
感觉它在通信的,它们之间 进行交流的目的。
比如说我这里再发送一些信息, 那这另外一端呢,它也就接收到
所以它是通过服务端来进行处理的。
那这里我们看看代码,怎么样来实现这样一个多线程的一个同时的一个
处理,先看看客户端,客户端相对来说简单一点点,这个客户端呢
当然它有各种界面对象,包括按钮啊,这个面板等等,这里我就不多说了。
我们下面呢,看看它里面的关键代码,就是开始连接
这个开始连接呢,一样的,是有一个socket,这个socket呢
然后我们把它封装成一个input StreamReader,再封装成一个BufferedReader,那这样呢我-
们就可以 写信息了,所以这里,同样的要注意啊,这个流有两个,一个是InputStream,一-
个是OutputStream 所以我们也有一个in一个out,两个流。
这样的话, 然后我们也开一个线程,这个线程里面的wrong方法做什么呢? 就是它要一直跟服务端进行通信,所以
在这里面呢也基本上是一个while true的一个无限循坏,这个无限循坏呢就接收信息
然后等待,并且呢处理信息,都是接收信息,处理信息。
那么接收信息呢,它实际上是从这个 流里面read一个line,就是得到信息
还有一个呢,处理信息,这个处理信息呢我们得到
要做的事情是什么呢?它就是把它呢用这个信息呢显示到界面上,我这里面呢是加到
列表框里头,同样呢也要用invokelater,因为我们现在呢是在那个线程里面 这是客户端。
总的来说客户端相对比较简单,它开了一个 连接以后呢,建了两个流,这两个流呢
再用一个线程来无限的处理它,这个无限制
来处理它,就包括接收信息,然后显示信息 处理信息实际上是显示信息。
另外一个, 当我们这个按钮,按到发送的时候呢,我们就用out这个流,把它写出去。
那么写到哪儿去呢,实际上是写到服务端,那我们下面呢再看看服务端。
请看这里,那服务端呢,它主要是一个监听的过程,那么监听的过程呢
我们就是new一个ServerSocket,也有一个端口号,那么这个servers-
ocket 然后呢我们就有一个线程,有个线程
这个线程呢要处理多个客户,所以这个线程里面也是一个accept
就是接受客户端的呼叫,但是又这个 socket呢,我们把它封装一下,封装成另一个
功能更强的一个叫connection,连接,表示这个连接对象,连接对象我们等一下再看
它当然主要的是呢,传递这个参数呢,是当前接收到的这个socket,
这个socket同时我们把这个连接 添加到一个集合里头去,这里专门有一个集合
这个集合呢就是在前面定义的 就是表示有多个连接,
这个集合,但这里呢我们可以用vector或者用list等等
当然,vector呢它是线程安全的, 所以方便一点点,它是这样一个集合。
所以我们也就说, 在服务端维持了一个多个连接,这样一个
数组,一个集合,以方便处理。
那我们下面看看这个连接是一个什么对象,连接
呢在这里我们又实现了它又是一个线程,也就是说,每一个连接呢
它都要实现那个线程,那这个线程里头
也有这个两个流,input一个流,output流,表示进行通信的。
线程里面做的事情呢又是一个无限的循环, 这个无限的循环呢,它也是接收信息,然后呢
这个服务端呢来处理信息。
但处理信息呢我们就可以呢 比如说得到一个信息,我可以把它发送给所有当前的这些连接
我们看看这个处理信息,这个处理信息呢做了两件事情。
一个是呢我们用invokelater,注意它因为在另一个线程里头 所以用,把它那个信息呢显示到
列表框里头里面,然后,还有一个呢,广播,这个广播信息,也就是
用一个循环把所有的这个信息啊
所有的,发送给所有客户,就是用一个循环,发到所有当前的这个的连接,
这样就达到一个服务端向所有的客户端发送信息的目的。
我们在这个简单的程序的基础上呢,可以做进一步的改进,比如说
我们发送的信息呢,除了这个交流的文字信息,我们还有一些特殊的信息,比如说以斜杠- 开始的,
我们就可以把它变成笑脸,或者呢我们以斜杠common开始呢,可以
把它理解成一个秘密,而不是理解为一个显示的文本 等等,甚至呢在这个基础上,我们可以做出一些类似于
网络对战这样的游戏。