今天是刘小爱自学Java的第45天。
感谢你的观看,谢谢你。
话不多说,开始今天的学习:
昨天学习了网络编程里的一些基本概念,今天开始代码实战演练,写一个TCP通信程序。
一、前提概述
TCP是有连接的通信协议。
1.既然是通信,那必须有客户端和服务端,毕竟一个人也没法通信。
2.客户端先发起请求,还记得昨天说的三次握手么?
客户端向服务端发起请求
服务端响应客户端
客户端再次发起请求,发送确认信息
3.服务端和客户端哪个先运行?
答案是服务端。虽然说三次握手中是客户端先发起请求,但是客户端发起请求时要先确定服务端是否存在。
就好比我们打电话结果对方是个空号,那不是白打了么?
所以要先启动服务端,保证它不是空号。
二、客户端代码
创建一个客户端类:TcpClient
客户端套接字
什么叫套接字?
就是IP+端口,在Java里面它就对应了一个类,叫Socket,也叫套接字。
通过它可以找到计算机中对应的进程。
构造方法中的参数即为服务端的IP+端口(因为我这只有一台计算机,故客户端和服务端用同一台计算机代替)。
向服务端发起请求(第一次握手)
发起请求:发信息给服务端,既然是发消息,那要使用到IO流中的输出流,也就是写内容。
getOutputStream()方法也就是获取一个流,再用输出流的write()方法写内容。
告诉服务器输出结束
这个是什么意思呢?
在IO流中读文件时是怎么判断读完了的?
返回值为-1时,就表示文件读完了,同时结束while循环。
但是这儿并不是文件,文件是死的,客户端是活的,服务器它并不确定客户端到底说完没有。
所以shutdownOutput()方法,就是相当于服务端读到这儿时返回值为-1,结束循环。
这个其实很好理解,我们平时打电话的时候有时也会出现抢话现象,这也许在生活中是无关紧要的小事,但是在程序中在一些特殊场合都会重视这个问题。
所以电视上有时候会看到那些会议场所,发言人说完一段话后会说一句Over,表示自己说完了,后面的人接着开始说,这样就不会出现抢话现象了。
shutdownOutput(),也就相当于这个Over
客户端接收服务端响应(第三次握手)
这个步骤是要在服务端接收客户端请求之后。
这个时候服务端已经接收到了信息,并也发信息过来,客户端接收其信息。
读信息自然就是IO流中输入流的read()方法:使用while循环,这段代码是IO流的基本代码。
关流
socket关流,虽然IO流这有几个,但都是socket的关联资源,所以只需要关闭socket就好了。
三、服务端代码
创建一个服务端类:TcpServer
服务端套接字
指定服务端的端口,IP也就是当前主机。
客户端要想访问这个服务端,那它填写的套接字要和服务端这儿的端口保持一致。
如果是两台电脑,我这台是服务端,另一台是客户端。
那我要把我的IP+端口告诉客户端,客户端在第一步中指定该IP+端口,就可以访问我这台电脑了。
接受客户端的请求
服务端的accept()方法,返回值就是Socket对象。
所以发现没有?socket就是服务端和客户端之间沟通的一个桥梁。
无论是读数据还是写数据都是基于socket的。
小时候玩过传声筒的小伙伴应该知道:两个人拿着传声筒,拉很远,讲话也能听到。
这个socket就好比这个传声筒。
读客户端的请求,也就需要IO流中的输入流:
socket.getInputStream()得到的就是一个输入流,再使用read()方法读取客户端的消息。
服务端响应客户端(第二次握手)
接到客户端的信息后,服务端要再次向客户端发送信息。
socket.getOutputStream()得到的就是一个输出流,再使用write()方法写发送给客户端的信息。
关流
和客户端一样的道理。
其中ServerSocket也要关流。
四、运行代码
前面也说过了,先运行服务端代码,再运行客户端,结果如下:
服务端控制台
服务端先运行代码,它运行后控制台上是没有输出的,它要等客户端向它发起请求。
其中服务端中accept方法是一个阻塞方法:
accept,接受的意思,就是接受客户端的请求。
如果客户端一直不向服务端发起请求,服务端就一直等,这样的话后面的代码都不会运行。
客户端一运行,向服务端发起请求,服务端上输出内容,就表明客户端的请求它接受到了。
客户端控制台
如果说服务端是被动方,开启后等待请求;那客户端就是主动方,它一运行整个程序就跑起来了。
客户端上输出内容,也就表明服务端的响应它接受到了,就可以互相通信了。
总结
领取专属 10元无门槛券
私享最新 技术干货